Мониторинг создания дочерних процессов с помощью Boost

Я создаю в своей программе процесс (скажем, процесс X), который может создавать дочерние процессы, и они могут делать то же самое, и мне трудно определить, когда дерево процессов завершено (= все потомки вышли).

Я не нашел для этого никакого прямого подхода к Boost.

Мое (не пуленепробиваемое) решение заключалось в том, чтобы поддерживать список отслеживаемых процессов, начиная только с процесса X в списке, и периодически отслеживать процессы в системе, а при обнаружении процесса - это родительский идентификатор. находится в списке, добавьте этот идентификатор процесса в список. как только я перехожу к циклу мониторинга, который показывает, что все процессы в списке завершены, дерево процессов завершается.

При таком подходе есть две основные проблемы:

  1. Процесс может «ускользнуть» - рассмотрите следующий поток:

    • Цикл мониторинга завершен, и отображается список [X].

    • Процесс X создает процесс Y, который создает Z и завершается.

    • Цикл мониторинга запущен - он не обнаружит процесс Y, поскольку он
      завершился, и не обнаружит процесс Z, потому что процесс Y не был обнаружен.

  2. Этот тип мониторинга требует значительных ресурсов, так как он должен запускаться очень часто, чтобы свести к минимуму эти «промахи», описанные в проблеме 1.

Некоторые фрагменты кода, используемые в моей программе:

Создание процесса X:

m_process = ps::execute(
                                  boost::process::initializers::set_cmd_line(...),
                                  boost::process::initializers::bind_stdout(sink), // route stdout to a sink/pipe
                                  boost::process::initializers::set_env(...),
                                  boost::process::initializers::start_in_dir(...),
                                  boost::process::initializers::throw_on_error());

Мониторинг процесса X (простой и недостаточный случай):

boost::system::error_code ec;
int tmp = ps::wait_for_exit(m_process,timeout,ec);

Важные примечания:

  1. У меня нет контроля над дочерним процессом (процесс X), и я не знаю, что он собирается делать или какие процессы он будет порождать.
  2. Мое решение должно соответствовать как Windows, так и Linux (если это невозможно, мне пришлось бы прибегнуть к использованию кода, специфичного для ОС, в моей программе, которая (до сих пор) не зависела от ОС).

person Ron.B.I    schedule 20.01.2015    source источник


Ответы (1)


Если вы можете изменить дочерние процессы, чтобы они сообщали об PID, которые они создают, используя какой-либо механизм IPC (stdout, очередь сообщений, разделяемая память, именованный канал ...), тогда у вас есть начало.

Вы можете использовать Boost Asio с полученными дескрипторами ( object_handle).

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

Я бы посоветовал, если вы контролируете дочерние процессы, вам гораздо лучше координировать работу с помощью IPC.

person sehe    schedule 20.01.2015
comment
У меня нет контроля над дочерним процессом (процесс X), и я не знаю, что он собирается делать или какие процессы он будет порождать. Я добавлю к вопросу это важное замечание. - person Ron.B.I; 20.01.2015
comment
@ Ron.B.I Как видите, я нашел подходящие ответы. Так что только в Linux это может оказаться утомительным, если только кто-нибудь не добавит - person sehe; 20.01.2015
comment
Что касается ответов: процессы внуков в нашем случае - это просто тестовый пример, я ищу общее решение, мы говорим о программном обеспечении для выполнения - возможность выполнять командную строку, предоставленную пользователем, на нескольких вариантах Linux и Windows , пользователь может запустить сценарий, который запускает установку, которая запускает другую установку, и тому подобное. Единственное, что нам известно, это корень дерева, который запускает мой процесс. Что касается ptrace, я изучаю это, но, к сожалению, как я уже сказал, я пытаюсь решить это как для Windows, так и для Linux. - person Ron.B.I; 20.01.2015
comment
@ Ron.B.I Ха. Для варианта windows это уже решено! Если вы действительно хотите ограничить использование ресурсов в Linux, вы можете использовать chroot + ulimit; ulimit имеет функции для ограничения количества порождаемых дочерних процессов, а также ограничения общего времени процессора, потребляемого дочерним + внуками (и другими вещами, такими как самый большой создаваемый файл, количество открытых файлов и т. д.) - person sehe; 20.01.2015
comment
Моя основная цель - предотвратить выполнение следующей командной строки до тех пор, пока дерево не будет завершено, учитывая логику получения информации о порождаемом дочернем процессе (без ограничения ресурсов), я могу легко отслеживать и определять, что дерево завершено. Бег. - person Ron.B.I; 20.01.2015
comment
Правильно. Это означает, что в Windows это решается с помощью связанного ответа (_ 1_). В Linux похоже, что вы должны обернуть верхний уровень fork / exec процессом, который использует prctl(2) для установки PR_SET_CHILD_SUBREAPER. Это означает, что вы можете (и должны) получать сигналы, когда любой ребенок умирает. Я полагаю, это оставляет загадку определения того, когда вы действительно закончили, и не осталось никаких внуков / зомби (но, по крайней мере, вы не остановитесь раньше) - person sehe; 21.01.2015