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

Evgeny Sinelnikov =?iso-8859-1?q?sin_=CE=C1_altlinux=2Eru?=
Ср Апр 16 06:01:27 MSD 2008


2008/4/16 Dmitry V. Levin <ldv at altlinux.org>:
> On Wed, Apr 16, 2008 at 04:03:19AM +0400, Evgeny Sinelnikov wrote:
>  > >  $ strace -qe waitpid ./waitpid
>  > >  waitpid(-1, 0xbf88880c, WNOHANG)        = -1 ECHILD (No child processes)
>  > >  waitpid(-1, 0xbf88880c, WNOHANG)        = -1 ECHILD (No child processes)
>  >
>  > Странный пример, у него же нет потомков, и нет обработчика SIGCHILD.
>  > Но он демонстрирует, что ECHILD приходит.
>
>  Он демонстрирует, что повторный waitpid снова приводит к ECHILD.
>
>
>  > >  > Это же подтверждено не практике. В моём случае стоит
>  > >  > ожидание только по этому сигналу, иначе цикл в killall() у меня вообще
>  > >  > не завершится... Но он завершается, а следовательно ECHILD, как и
>  > >  > ожидается, приходит...
>  > >
>  > >  ECHILD у init произойдёт только в случае если в системе не останется
>  > >  процессов, у которых ppid==1; такое может произойти, но может и не
>  > >  произойти.  У нас на стенде init не получал ECHILD ни разу.
>  >
>  > Такое обязательно произойдёт, если этого дождаться... Иначе нет
>  > никакой гарантии, что процессы, занявшие ресурсы /mnt/destination
>  > завершены. В коде же инсталятора это ожидание раньше полагалось на
>  > секунду после первого общего сигнала. А то, что оно не происходило
>  > означает, что никогда не было момента, чтобы последний сигнал был
>  > получен и успел быть обработан. Хотя конечно это странно...
>  >
>  > ECHILD может быть не получен, только, если последний процесс не
>  > пришлёт SIGCHILD... Если такое вдруг произойдёт, то таймаут, конечно,
>  > выход...
>
>  ECHILD может не случиться, если в системе остался хотя бы один процесс
>  с ppid==1, который не собирается завершаться.  На нашем стенде это
>  происходит всегда.
>

Даже когда ему SIGKILL отправили не отрывается... ? Хм... Ну, всякое
бывает, но это какие-то проблемы ядра. Сизифный вариант на 2.6.24
такого не давал ни разу.... Теперь понятно почему ранее не выявлялся
баг с killall()...

>
>  > Текущий вариант (когда превратиться в alt14) должен быть вполне
>  > работоспособен... Вот только 5 секунд - это маловато...
>
>  А вот мне кажется, что и 5 секунд многовато.  Не договоримся. :)
>

Ну, скажем так, пока это вероятно приемлимо...

>
>  > Ведь sleep()
>  > прерывается во время прихода сигнала и, при интенсивном приходе
>  > SIGCHILD на этапе ожидания завершения процессов, может пять раз подряд
>  > прерваться может. И никакой гарантии, что 6 и 7 процессы ещё не
>  > завершились нет. Статистически же поймать это будет теперь ещё
>  > сложнее...
>
>  Можно использовать альтернативную реализацию sleep(3), например:
>
>  static void mysleep(time_t sec)
>  {
>         struct timespec req = { sec, 0 }, rem;
>
>         for (; req.tv_sec || req.tv_nsec; req = rem)
>                 if (!nanosleep(&req, &rem))
>                         break;
>  }
>

Как-то оно не очень... Вся прелесть была как раз в том, что sleep()
отрывался после очередной обработки сигнала и, если это был последний
процесс, то переменная got_ECHILD была уже установлена... Холостое
ожидание было сведено к минимуму... Если конечно таких багов не было
бы, когда процессы зависают... А для того, чтобы этот процесс был
виден точки рисуютс как раз... У меня ни разу не было видно как они
рисуются... Моментально пробегают и тут же ECHILD ловится....


-- 
Sin (Sinelnikov Evgeny)


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