Должен ли я беспокоиться о порядке, в котором процессы в группе получают сигналы? - PullRequest
4 голосов
/ 10 июля 2010

Я хочу завершить группу процессов, отправив SIGTERM процессам внутри нее.Это может быть выполнено с помощью команды kill, но в руководствах, которые я нашел, мало информации о том, как именно это работает:

   int kill(pid_t pid, int sig);
   ...
   If pid is less than -1, then sig is sent to every  process  in
   the process group whose ID is -pid.

Однако, в каком порядке сигнал будет отправляться процессам, которые формируютгруппа?Представьте себе следующую ситуацию: между группой ведущий и ведомый процессы в группе устанавливается канал.Если ведомое устройство уничтожено во время обработки kill(-pid), в то время как ведущее устройство еще не выполнено, ведущее устройство может сообщить об этом как о внутреннем сбое (после получения уведомления о том, что дочерний элемент мертв).Однако я хочу, чтобы все процессы понимали, что такое завершение было вызвано чем-то внешним для их группы процессов.

Как я могу избежать этой путаницы?Должен ли я делать что-то большее, чем просто kill(-pid,SIGTERM)?Или это разрешается базовыми свойствами ОС, о которых я не знаю?

Обратите внимание, что я не могу изменить код процессов в группе!

Ответы [ 4 ]

5 голосов
/ 12 июля 2010

Попробуйте сделать это в три этапа:

kill(-pid, SIGSTOP);
kill(-pid, SIGTERM);
kill(-pid, SIGCONT);

Первый SIGSTOP должен перевести все процессы в остановленное состояние. Они не могут поймать этот сигнал, поэтому это должно остановить всю группу процессов.

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

SIGCONT снова запустит процессы, позволяя доставить SIGTERM. Если ведомый сначала получает сигнал SIGCONT, мастер все равно может быть остановлен, поэтому он не заметит, что раб уходит. Когда мастер получает SIGCONT, за ним следует SIGTERM, завершающий его.

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

1 голос
/ 16 июля 2010

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

Даже ваш STOP / TERM/ CONT последовательность будет уязвима для этого.

Боюсь, вам может понадобиться что-то более сложное.Возможно, дочерний процесс мог бы перехватить SIGTERM, а затем выполнить цикл, пока его родительский процесс не завершится, прежде чем он сам выйдет?Если вы сделаете это, обязательно добавьте тайм-аут.

1 голос
/ 10 июля 2010

Насколько я понимаю, вы не можете полагаться на какой-либо конкретный порядок доставки сигнала.

Вы можете избежать этой проблемы, если отправите сигнал TERM только главному процессу, а затем попросите мастера убить его потомков.

0 голосов
/ 16 июля 2010

Не проверено: используйте разделяемую память и вставьте в своего рода семафор «мы умираем», который может быть проверен перед тем, как ошибки ввода / вывода будут рассматриваться как реальные ошибки.mmap () с MAP_ANONYMOUS | MAP_SHARED и убедитесь, что он переживет ваш путь fork() процессов.

О, и обязательно используйте ключевое слово volatile, иначе ваш семафор будет оптимизирован.

...