LINUX.ORG.RU

Ответ на: комментарий от Legioner

> Так одна из функций инита - убивать зомби, разве нет?

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

mukoh
()
Ответ на: комментарий от mukoh

> Так одна из функций инита - убивать зомби, разве нет?



Нет.



да.

а зомби ему в нагрузку от ядра достаются, если родитель

зомби завершается, не упокоив своих детей, пребывающих


в состоянии зомби..



не только зомби, а вообще любой процесс, если его parent
exits.

если он уже zombie, init'у посылается SIGCHLD, init
сделает wait(). кстати, это, вообще-то, нафиг не нужно,
мы могли бы зачистить его во время reparenting, но так
уж повелось.

idle ★★★★★
()
Ответ на: комментарий от idle

> да.

Тогда верно ли утверждение «init не может иметь zombie в качестве детей»? И почему?

не только зомби, а вообще любой процесс, если его parent exits.

Ну да, не только зомби. Речь просто про зомби была.

если он уже zombie, init'у посылается SIGCHLD, init сделает wait(). кстати, это, вообще-то, нафиг не нужно, мы могли бы зачистить его во время reparenting, но так

уж повелось.

Если звезды зажигают, значит это кому-нибудь нужно? Вопрос почему так повелось?

mukoh
()
Ответ на: комментарий от mukoh

> Тогда верно ли утверждение «init не может иметь

zombie в качестве детей»? И почему?


это. init - это просто программа. можно написать что
угодно. но любой «правильный» init должен реагировать
на SIGHCLD.

вообще-то, если говорить о Linux kernel, то init может
игнорировать этот сигнал, тогда ядро само зачистит
reparented zombie.

Вопрос почему так повелось?


да хрен его знает. скорее всего, по историческим
причинам. я мало что знаю про историю Unix, но когда-то
init был действительно особым процессом.

в linux это тривиально было бы убрать. но никому не
нужен user-visible change без особых причин.

почти то же самое с kernel panic в случае завершения
init. у ядра нет никаких причин для такого поведения,
можно было бы этого не делать (с минимальными изменениями).
только вот, маньяки из selinux team упираются.

idle ★★★★★
()
Ответ на: комментарий от GotF

Круть! У кого-то много свободного времени :)

svu ★★★★★
()
Ответ на: комментарий от idle

> это. init - это просто программа. можно написать что угодно. но любой «правильный» init должен реагировать на SIGHCLD.

Ну вот есть у нас скажем инит, процесс-родитель и процесс-потомок, пусть процесс-родитель у нас является потомком инита. Предположим, наш процесс-потомок завершается, при этом посылается SIGCHLD его родителю, то есть процессу-родителю. Наш процесс-потомок становится зомби. Если процесс-родитель кривой, то он может этот сигнал не обработать и завершиться. Процессов-потомков у него нет, ибо зомби это уже не процесс, а так, слот в таблице процессов. Наш инит получит SIGCHLD от имени процесса-родителя, и сделает для него waitpid(). Что будет в этот момент с зомби-потомком? Сигнал SIGCHLD от него уже был послан процессу-родителю, который теперь сдох, посылать сигнал еще раз вроде как уже и нечему, ибо процесс завершился, осталась только запись в таблице процессов. Что будет? init будет вызывать waitpid() до посинения^W тех пор, пока тому есть что возвращать? Или его надо будет пнуть каким-то образом?

вообще-то, если говорить о Linux kernel, то init может игнорировать этот сигнал, тогда ядро само зачистит reparented zombie.

Это, насколько я помню, относится вообще к любому процессу, и не только в линуксе, ибо это часть POSIX - если явно заигнорировать SIGCHLD, то в момент смерти потомка его код завершения и прочая ерунда, которая в противном случае осталась бы болтаться в виде зомби, будет выброшена и слот в таблице процессов освобожден вместе со всеми ресурсами.

да хрен его знает. скорее всего, по историческим причинам. я мало что знаю про историю Unix, но когда-то init был действительно особым процессом.

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

Поскольку инит за чужие ошибки вроде как отвечать не должен, то вроде как ему и нет смысла держать чужих зомби (со своими детьми а также сииротами он разбираться умеет), поэтому вроде имеет смысл их упокоить, если есть такая возможность. Но однако - был вопрос «что будет если зомби будет у инита» значит они таки бывают? Плюс в разнообразных FAQ указывается, что если зомби у инита, то поможет только перезагрузка. Не исключено, что эти FAQ'и просто устарели.

Вот поэтому и хочется понять, как есть на самом деле.

ЗЫ: в той же preap есть явная проверка, и если у зомби инит в качестве родителя, то она завершает работу (впрочем, это просто может быть особенностью реализации).

mukoh
()
Ответ на: комментарий от mukoh

> Если процесс-родитель кривой, то он может этот сигнал

не обработать


да

Сигнал SIGCHLD от него уже был послан процессу-родителю


да

Что будет в этот момент с зомби-потомком?


я уже говорил, будет послан SIGCHLD init'у

Это, насколько я помню, относится вообще к любому процессу


не совсем.

если явно заигнорировать SIGCHLD, то в момент смерти потомка


а мы говорили не про момент смерти, а про zombie reparenting.
и, кстати, до (сравнительно) недавнего времени kernel этого
не делал.

ошибки в реализации процесса-родителя в части работы с детьми.


да почему ошибки? скажем, админ прибил процесс, у которого
есть zombie child. и что теперь?

да многое делается по историческим причинам. ну вот, например,
init нельзя было ptrace'ить (у меня man ptrace до сих пор так
думает). с большим трудом это было отменено, при том что
patch был тривиальный.

значит они таки бывают?


вот этого вопроса я не понимаю. еще раз. они _не_ бывают
при нормальном поведении init. но к kernel это уже никакого
отношения не имеет.

Вот поэтому и хочется понять, как есть на самом деле.


kernel/exit.c:forget_original_parent()

в той же preap


в linux нету

idle ★★★★★
()
Ответ на: комментарий от idle

> _не_ бывают при нормальном поведении init.

на всякий случай, если это вдруг не понятно...

разумеется, у нас всегда есть какое-то окно
прежде чем init сделает wait.

ну, и если этот zombie под отладчиком, он будет
«висеть» пока дебаггер не отпустит. но все это
почти офтопик.

idle ★★★★★
()
Ответ на: комментарий от idle

> > Что будет в этот момент с зомби-потомком?

я уже говорил, будет послан SIGCHLD init'у


Кем? В случае завершающегося процесса-родителя это делает поток, исполняющий код для завершения процесса. Для процесса-потомка этот код уже давно выполнился. Иными словами, сколько сигналов SIGCHLD будет послано?

если явно заигнорировать SIGCHLD, то в момент смерти потомка

а мы говорили не про момент смерти, а про zombie reparenting.


Понял. Я просто немного другое имел ввиду.

ошибки в реализации процесса-родителя в части работы с детьми.

да почему ошибки?


Потому что исторически :-)

скажем, админ прибил процесс, у которого есть zombie child. и что теперь?


Угу. Но ведь откуда-то этот зомби взялся изначально? Значит родитель про него забыл, не обработал, не успел, etc

значит они таки бывают?

вот этого вопроса я не понимаю. еще раз. они _не_ бывают при нормальном поведении init.


Не бывают, в смысле вероятность увидеть их мала.. Понятно, что они бывают как минимум между моментом когда ядро перецепляет их к иниту, и временем, когда произходит фактическая обработка waitpid().

но к kernel это уже никакого отношения не имеет.


Да собственно инит к kernel тоже уже никакого отношения не имеет :-)

Вот поэтому и хочется понять, как есть на самом деле.

kernel/exit.c:forget_original_parent()


Спасибо. Однако глядя на эту функцию, становится понятно, что сигнал посылается не всегда, а только тогда, когда pdeath_signal - не ноль, и не SIGCHLD, a тот, что в pdeath_signal записан. А записать туда что-то можно вызвав сисколл prctl. То есть по сути все отдается на откуп юзерленду.

mukoh
()
Ответ на: комментарий от mukoh

> Кем?

ядром.

сколько сигналов SIGCHLD будет послано?


ну два же ;)

Значит родитель про него забыл, не обработал


совсем не обязательно. напр, SIGCHLD был временно
заблокирован, а админ его прибил. или просто не успел.
или parent/child вызвали exit() «одновременно».

на самом деле, я не очень понимаю, что тебя здесь
смущает.

они бывают как минимум между моментом


ну, это очевидно. я даже написал об этом в следующем
посте, чтобы никто не придрался ;)

pdeath_signal


ты не туда смотришь. это совсем другое, это сигнал от
parent к child.

см forget_original_parent()->reparent_leader()->
-Юdo_notify_parent()->__group_send_sig_info()

в этот момент новый parent уже init.

все отдается на откуп юзерленду


нет, юзерленд здесь не рулит.

idle ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.