read () зависает на процессе зомби - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть цикл while, который читает данные из дочернего процесса, используя блокировку ввода-вывода, перенаправляя stdout дочернего процесса в родительский процесс.Обычно, как только завершается дочерний процесс, в этом случае возвращается блокировка read(), поскольку канал, из которого выполняется чтение, закрывается дочерним процессом.

Теперь у меня есть случай, когда read()вызов не завершается для дочернего процесса, который заканчивается в состоянии зомби.Таким образом, операционная система ждет, пока мой код пожнет его, но вместо этого мой код блокируется при вызове read().

У самого дочернего процесса нет никаких дочерних процессов, работающих во время зависания,и я не вижу никаких файловых дескрипторов, перечисленных при поиске в /proc/<child process PID>/fd.Дочерний процесс, тем не менее, разветвлял два демонических процесса, цель которых, по-видимому, заключается в мониторинге дочернего процесса (дочерний процесс является проприетарным приложением, над которым я не имею никакого контроля, поэтому трудно сказать наверняка).

При запуске из терминала дочерний процесс, который я пытаюсь read() из, автоматически завершается, и, в свою очередь, демон, обрабатывающий его разветвленную систему, также завершается.

Версия Linux 4.19.2.

Что может быть причиной того, что read() не возвращается в этом случае?

Последующие действия: Как избежать зависания `read ()` в следующей ситуации?

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Возможная (самая распространенная) причина для блокировки read(2) в канале с мертвым дочерним элементом заключается в том, что родитель не закрыл сторону записи канала, поэтому для этого все еще есть открытый (для записи) дескриптор.труба.Закройте сторону записи канала в родительском процессе перед чтением из него.Ребенок мертв (вы сказали, зомби), поэтому это не может быть процесс с открытой стороной записи трубы .И не забудьте wait(2) для ребенка в родительском доме, или вы получите систему, полную зомби :)

Помните, что вы должны сделать два закрытия в своем коде:

  • Один в родительском процессе, чтобы закрыть сторону записи канала, оставив родительский процесс только с дескриптором чтения.

  • Один в дочернемпроцесс (непосредственно перед exec(2) ing) закрывает сторону чтения канала, оставляя дочерний процесс только с дескриптором записи.

В случае, если вы хотите использовать pipe(2) дляотправьте информацию ребенку, измените чтение на письменное и наоборот в вышеуказанных двух пунктах.

0 голосов
/ 30 ноября 2018

Дочерний процесс, однако, запустил два процесса-демона ... В чем может быть причина того, что read() не возвращает в этом случае?

У разветвленных процессов по-прежнему открыт дескриптор файлакогда ребенок заканчивается.Следовательно, read call никогда не возвращает 0.

Эти процессы-демоны должны закрыть все файловые дескрипторы и открыть файлы для ведения журнала.

...