Как отслеживать все процессы потомков для очистки?

у меня есть программа, которая может fork() и exec() несколько процессов в цепи. Е. Г.: процесс --> вилка / ОТВ Б --> вилки, старпома с --> вилки, Exec и т. д. Так что это пра-пра-дедушка из с.

Теперь проблема в том, что у меня нет никакого контроля над процессами B, C и D. Итак, может произойти несколько вещей.

  1. может случиться так, что процесс потомка может сделать setsid() для изменения группы процессов и сессии.
  2. или один из потомков процесс умирает (скажем, C), и, следовательно, его ребенок (D) воспитывается init.

поэтому я не могу полагаться на идентификатор группы процессов или родительский идентификатор для отслеживания всех потомков A. Есть ли надежный способ отслеживания всех потомков? Более конкретно, я хотел бы убить всех потомков (сирот и других).

было бы также здорово, если его POSIX совместимый.

2 ответов


я согласен с cafобщее настроение: если процесс вызывает setsid, Он говорит, что хочет жить самостоятельно, несмотря ни на что . Тебе нужно хорошенько подумать, действительно ли ты хочешь их убить.

это, как говорится, иногда, вы захотите, чтобы какая-то форма "супер-сессии" содержала дерево процессов. В POSIX toolbox нет инструмента, который предоставляет такие супер-сессии, но я собираюсь предложить несколько решений. Каждое решение имеет свои ограничений, поэтому вполне вероятно, что они не применимо к вашему случаю, но, надеюсь, один из них будет подходящим.

чистым решением является запуск процессов в собственной виртуализированной среде. Это может быть FreeBSD-style тюрьмы, Linux группы, или любой другой вид технологий виртуализации. Ограничения этого подхода заключаются в том, что технологии виртуализации зависят от ОС, и процессы будут выполняться в несколько ином контекст.

если у вас есть только один экземпляр этих процессов в системе, и вы можете использовать root, запустите процессы как выделенный пользователь. Супер-сеанс определяется как процессы, выполняющиеся как выделенный пользователь. Убейте потомков kill(-1, signum) (обратите внимание, что это убьет сам процесс убийцы, если он не заблокирован или не обработан сигналом).

вы можете сделать процесс открыть уникальный файл, убедившись, что FD_CLOEXEC флаг установлен на файл дескриптор. Затем все дочерние процессы наследуют открытый файл, если они явно не удаляют FD_CLOEXEC флаг перед вызовом execve или закройте файл. Убейте процессы с помощью fuser -k или путем получения списка идентификаторов процессов с fuser или lsof (fuser находится в POSIX, но не fuser -k.) Обратите внимание, что есть условие гонки: процесс может разветвиться между временем вызова fuser и времени вы убили его, поэтому вам нужно позвонить fuser в цикле, пока не появится больше процессов (не цикл, пока все процессы не умрут, так как это может быть бесконечный цикл, если один из процессов блокирует ваш сигнал).

вы можете создать уникальную случайную строку и определить переменную среды с этим именем или с известным именем и этой уникальной строкой в качестве значения. Он будет унаследован всеми процессами-потомками, если они не решат изменить свою среду. Нет портативного способа поиска процессов на основе их среды или даже получения среды другого процесса. Во многих вариантах unix вы можете получить информацию с опцией ps (например,ps -e on *BSD или ps e в Linux); информация может быть нелегкой для анализа, но наличие уникальной строки является достаточным индикатором. Как с fuser выше, обратите внимание на необходимость цикла, чтобы избежать состояния гонки, если потомок вызывает fork слишком поздно для вас, чтобы заметить своего ребенка, но прежде чем ты можешь убить родителя.

вы можете LD_PRELOAD небольшая библиотека это разветвляет поток, который прослушивает канал связи и убивает его процесс при уведомлении. Это может нарушить процесс, если он ожидает узнать обо всех своих собственных потоках; это только возможность на архитектурах, где стандартная библиотека всегда потокобезопасна, и вы пропустите статически связанные процессы. Канал связи может быть любым, что позволяет ведущему процессу транслировать приказ о самоубийстве; одна из возможностей-это канал, где каждый процесс-потомок выполняет блокировку чтения и процесс предка закрывает канал, чтобы уведомить потомков. Передайте номер дескриптора файла через переменную среды.


способ POSIX сделать это-просто использовать группы процессов. Процессы-потомки, которые явно изменяют свою группу процессов / сеанс, принимают преднамеренное решение не чтобы их жизнь отслеживалась их первоначальным родителем - они специально освобождают себя от родительского контроля. Такие процессы не являются сиротами - это взрослые, которые "вылетели из гнезда" и хотят контролировать свою жизнь.