- У меня есть программа, которая
popen()
к другому, а такжеdup()
стандартный вывод - При вызове из другого процесса (например, на примере PHP) или через SSH, процесс не выходит.
process_test.c
:Почему dup() и popen() не позволяют моему процессу выйти из него при вызове из другого процесса?
#include <stdio.h>
#include <unistd.h>
int main() {
int out;
out = dup(STDOUT_FILENO);
// close(out);
popen("sleep 10\0", "r");
}
Compile с gcc process_test.c
, работать с:
./a.out
-> выходит нормальноruby -e 'system("./a.out");'
-> нормально завершаетсяphp -r passthry("./a.out");
-> виситssh remotehost ./a.out
-> висит- , когда я не
dup
STDOUT или закрыть DUP, он не висит
Это самый короткий воспроизводимый код, который я мог найти, который показывает мне поведение я хотел бы чтобы лучше понять.
Чтобы извлечь это из нескольких PHP-приложений/фреймворков, потребовалось несколько часов, используя fork/pcntl/etc. чтобы измерить их отношения, т. е. я не писал этого или не сделал это; но, очевидно, весь смысл этого потерялся из-за того, что я все разобрал.
Вопросы
- Почему некоторые вызовы вешают (PHP, SSH) и другие не (рубин)?
- Даже когда я закрываю fd после popen, моя программа зависает; Зачем?
Я читал, что вы написали, но некоторые формулировки сбивает с толку: «... чтобы закрыть канал 2 совмещены с каналом 0 и 2 ...», что это такое должен означать? И вопрос: почему вызывающий (ssh) зависит от таких внутренних деталей, что делает этот процесс, я имею в виду, что он выглядит настолько хрупким? Например. Не имеет значения, когда я закрываю обманутый канал * после * popen(), ssh также не выйдет. – mark
Я перефразировал свои вопросы, а также добавил твист, что даже закрытие fd ** после того, как ** 'popen' не будет выходить в описанных обстоятельствах. – mark
Процесс ssh, если вы смотрите на исходный код, похож на rlogin или telnet: после открытия и установления соединения с удаленной программой запустите его, и поэтому входной канал ssh отображается на входном канале удаленной программы, поэтому для канала 1 и 2. ssh закроет соединение, когда все каналы открыты (т.е.: 0, 1, 2) закрыты. Поэтому, поскольку вы дублировали 1 канал, чтобы выполнить некоторые другие работы, ssh закончится, когда этот процесс завершится и закроет дублированный канал 1. Кажется, очень сложно описать, что 30 лет назад использовалось много такого поведения .... – gaetanoM