Как я могу надежно отслеживать процессы ребенка / внука в системе POSIX? - PullRequest
3 голосов
/ 11 июня 2009

У меня есть интересная (по крайней мере для меня) проблема: мне не удается найти способ надежного и портативного получения информации о процессах внуков в некоторых случаях. У меня есть приложение, AllTray , которое я пытаюсь заставить работать в некоторых странных случаях, когда его подпроцесс порождает ребенка, а затем умирает. Задача AllTray состоит в том, чтобы прикрепить приложение к панели задач, которая (обычно) указывается в виде командной строки для вызова AllTray (т. Е. alltray xterm запускает xterm и управляет им в AllTray).

Большинство программ с графическим интерфейсом прекрасно работает под ним. Он устанавливает свойство _NET_WM_PID в своем окне (или в библиотеке виджетов), и все хорошо, потому что _NET_WM_PID == fork() ed child. Однако в некоторых случаях (например, при запуске oowriter или программном обеспечении, написанном для работы под KDE, например K3b), дочерний процесс, который запускается AllTray, является оболочкой, будь то сценарий оболочки (как в случае OO.o) или странная программа, которая fork() s и exec() s сама по себе и эффективно фоновая, поскольку родительский процесс умирает очень рано.

У меня была идея не пожинать свои дочерние процессы, чтобы сохранить в таблице процессов идентификатор родительского процесса для моих внуков, чтобы я мог связать их со мной, обходя семейное древо снизу вверх , Однако это не работает: как только мой дочерний процесс умирает и превращается в зомби, система считает процесс моего внука сиротой и init принимает его. Похоже, это относится как минимум к Linux 2.6 и NetBSD; Я бы предположил, что это, вероятно, норма, и POSIX, похоже, не указывает, что это так, поэтому я надеялся на обратное.

Поскольку этот подход не сработает, я подумал об использовании LD_PRELOAD и перехвате вызова моего дочернего процесса к fork() и передаче информации обратно в мой родительский процесс. Тем не менее, я обеспокоен тем, что оно не будет таким портативным, как идеальное решение, потому что разные системы имеют разные правила о том, как динамический компоновщик делает такие вещи, как LD_PRELOAD. Он не будет работать для приложений с графическим интерфейсом setuid / setgid без вспомогательной библиотеки, также не настроенной на setuid или setgid, по крайней мере, в системах Linux. Вообще, это пахнет как плохая идея для меня, и кажется довольно хакерским.

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

1 Ответ

1 голос
/ 11 июня 2009

Вы можете изучить возможность использования групп процессов для отслеживания групп процессов. Группа процессов - это свойство (просто число), которое вы можете установить перед разветвлением, а потом дочерние процессы наследуют его автоматически.

AllTray может создать новую группу процессов для каждого приложения, запущенного с ним. Вы можете отправлять сигналы всем членам группы процессов. Я полагаю, что наиболее полезными сигналами здесь будут TERM и KILL, чтобы убить приложение, управляемое в AllTray.

Я не уверен, есть ли удобный способ выяснить, все ли участники группы процессов уже вышли или нет. Возможно, вам придется обратиться к полному списку процессов и вызвать getpgid для каждого процесса, чтобы узнать, остались ли какие-либо из них в группе процессов.

Обратите внимание, что группы процессов не будут работать для приложений, которые сами создают новые группы процессов. Но это относительно редко, и вам, вероятно, не нужно беспокоиться о таких приложениях.

...