[devel] q: installer: Killing all remaining processes (forever)

Evgeny Sinelnikov =?iso-8859-1?q?sin_=CE=C1_altlinux=2Eru?=
Ср Апр 16 04:03:19 MSD 2008


2008/4/16 Dmitry V. Levin <ldv на altlinux.org>:
> On Wed, Apr 16, 2008 at 01:39:20AM +0400, Evgeny Sinelnikov wrote:
>
> > >  Логика такая: поскольку не все процессы после рассылки SIGKILL
>  > >  завершаются, дожидаться появления ECHILD бесполезно.
>  >
>  > Логика, как мне кажется, ошибочна... ECHILD приходит, когда последний
>  > процесс умирает.
>
>  Почему вы так решили?
>

Потому, что обработчик сигнала так устроен. Когда приходит сигнал
SIGCHILD от последнего процесса, обработчик пытается запустить цикл
для других возможных зомби. И, поскольку это был последний процесс,
сразу же получает ECHILD.

ECHILD (for waitpid() or waitid()) The process specified by pid
(waitpid()) or idtype and id (waitid()) does not exist or is not a
child  of the calling process.  (This can happen for one's own child
if the action for SIGCHLD is set to SIG_IGN.  See also the Linux Notes
section about threads.)

>  "The waitpid() function shall fail if:
>  [ECHILD] The process specified by pid does not exist or is not a child of
>  the calling process, or the process group specified by pid does not exist
>  or does not have any member process that is a child of the calling
>  process."
>
>  Пример:
>
>  $ cat waitpid.c
>  #include <sys/wait.h>
>  int main(void)
>  {
>         int status;
>         waitpid(-1, &status, WNOHANG);
>         waitpid(-1, &status, WNOHANG);
>         return 0;
>  }
>
>  $ strace -qe waitpid ./waitpid
>  waitpid(-1, 0xbf88880c, WNOHANG)        = -1 ECHILD (No child processes)
>  waitpid(-1, 0xbf88880c, WNOHANG)        = -1 ECHILD (No child processes)
>

Странный пример, у него же нет потомков, и нет обработчика SIGCHILD.
Но он демонстрирует, что ECHILD приходит.

>  > Приход именно этого сигнала выдавал предупреждение,
>  > когда не до конца ожидался момент умирания всех процессов перед
>  > отмонтированием. По сути получается так, что при умирании последнего
>  > процесса, цикл в обработчике сигнала вынужден получить такую ошибку.
>  > Поэтому отключение обработчика сигнала перед циклом ожидания
>  > неверно...
>
>  Отключение обработчика сигнала?  Мы точно говорим про один и тот же код?
>

Да, я понял, что ошибся... То, что я писал про chld_handler(0)
неверно... Только толку в нём немного, хотя можно и оставить... вдруг
все процессы уже завершились, но каким-то образом последний не прислал
SIGCHILD.

>
>  > Это же подтверждено не практике. В моём случае стоит
>  > ожидание только по этому сигналу, иначе цикл в killall() у меня вообще
>  > не завершится... Но он завершается, а следовательно ECHILD, как и
>  > ожидается, приходит...
>
>  ECHILD у init произойдёт только в случае если в системе не останется
>  процессов, у которых ppid==1; такое может произойти, но может и не
>  произойти.  У нас на стенде init не получал ECHILD ни разу.
>

Такое обязательно произойдёт, если этого дождаться... Иначе нет
никакой гарантии, что процессы, занявшие ресурсы /mnt/destination
завершены. В коде же инсталятора это ожидание раньше полагалось на
секунду после первого общего сигнала. А то, что оно не происходило
означает, что никогда не было момента, чтобы последний сигнал был
получен и успел быть обработан. Хотя конечно это странно...

ECHILD может быть не получен, только, если последний процесс не
пришлёт SIGCHILD... Если такое вдруг произойдёт, то таймаут, конечно,
выход...

Текущий вариант (когда превратиться в alt14) должен быть вполне
работоспособен... Вот только 5 секунд - это маловато... Ведь sleep()
прерывается во время прихода сигнала и, при интенсивном приходе
SIGCHILD на этапе ожидания завершения процессов, может пять раз подряд
прерваться может. И никакой гарантии, что 6 и 7 процессы ещё не
завершились нет. Статистически же поймать это будет теперь ещё
сложнее...

-- 
Sin (Sinelnikov Evgeny)


Подробная информация о списке рассылки Devel