Когда запускается новый процесс, его потоки ввода/вывода STD(IN|OUT|ERR) определяются родительским процессом. Например, делая
cat - в консоли, родительским процессом будет командный интерпретатор (`bash`, zsh, etc), а его (интерпретатора) STD(IN|OUT|ERR) уже связаны с терминалом. cat же просто унаследует тот же набор.Когда мы запускаем новый процесс программно (fork + exec), мы можем указать его STD(IN|OUT|ERR) файловые дескрипторы (`man dup`). Но по умолчанию форкнутый процесс просто наследует потоки родителя.
Когда мы запускаем новый процесс программно (fork + exec) и хотим дождаться его завершения, нам всего лишь нужно вызвать
waitid() (`man waitpid`) в родительском процессе.Когда мы хотим прочитать то, что запущенный нами процесс печатает в свой STDOUT, можно создать pipe (`man pipe`) и указать его в качестве соответствующего файлового дескриптора для нового процесса, а затем начать читать из этого pipe в родительском процессе.
Когда процесс форкает другой процесс, а затем сам завершается, потоки, унаследованне форком не будут закрыты.
А теперь представьте ситуацию - мы запускаем (fork + exec) процесс (назовем его стартер), который в свою очередь запускает новый процесс (назовем его демон), а сам завершается печатая статус на экран. И в нашем коде мы хотим а) дождаться завершения стартера б) прочитать статус из его STDOUT.
Оказывается, если стартер-процесс не переназначил STD(IN|OUT|ERR) демона,
waitpid() нам благополучно сообщит, что стартер завершился, но вот блокирующая операция чтение из pipe на нашей стороне приведет к зависанию нашего процесса до окончания выполнения (в общем случае долгоживущего) демона. И это вряд ли то, что нам нужно. Фактически, демон наследует STDOUT стартера и, несмотря на то, что стартер уже давно завершился, файловый дескриптор останется открытым в течение всей жизни демона.Вывод - стартеры должны быть умными =) А самое смешное, что вездесущий runc (https://github.com/opencontainers/runc) - пример неумного стартера. Пруф https://github.com/cri-o/cri-o/blob/8a43af20119ad8fe1ffebb4128d8938134eaaeb1/conmon/conmon.c#L1336-L1342. Это умный стартер неумного стартера.