Отсоединить дочерний процесс от родительского

Отсоединить дочерний процесс от родительского

07.10.2017 05:44:51 Просмотров 28 Источник

Когда дочерний процесс, разветвленный от родителя, умирает, он все еще существует в некоторой степени и остается в состоянии зомби, пока он не будет пожат из вызова wait ().

Можно ли отделить эти отношения между родителями и детьми, и дети будут автоматически пожаты? Может быть, сирота от ребенка к иниту, или что-то еще?

Возможный вариант использования: создание большого количества процессов fire-and-forget в долгоживущей программе, без "удержания" на растущем списке зомби-PID, которые не могут быть переработаны ОС.

У вопроса есть решение - Посмотреть?

Ответы - Отсоединить дочерний процесс от родительского / Detach child process from parent

Является ответом!
Andrew Henle

07.10.2017 05:58:28

Согласно документации POSIX _exit() :

Если родительский процесс вызывающего процесса установил свой SA_NOCLDWAITфлаг или установил действие для сигнала SIGCHLDв SIG_IGN:

  • Информация о состоянии процесса (см. информацию о состоянии), если таковая имеется, должна быть удалена.

  • Время жизни вызывающего процесса должно закончиться немедленно. Если SA_NOCLDWAIT сигнал отправляется в родительский процесс.

  • Если поток в Родительском процессе вызывающего процесса заблокирован в SIGCHLD, wait()или waitpid(), и родительский процесс имеет ни один из оставшихся дочерних процессов в наборе ожидаемых детей, waitid(), wait()или waitid()завершится ошибкой и установит waitpid() для [errno].

Иначе:

  • Должна быть сформирована информация о состоянии (см. информацию о состоянии).

  • Вызывающий процесс должен быть преобразован в зомби-процесс . Информация о его статусе должна быть предоставлена в распоряжение родительского процесса. пока не закончится срок службы процесса.

  • ...

Короче говоря, чтобы предотвратить превращение дочерних процессов в зомби-процессы, проще всего вызвать ECHILD

ОБНОВЛЕНИЕ

Это влияет на способность ждать любого дочернего процесса, который может быть нежелательным. Функция sigignore( SIGCHLD );позволяет процессу отделить себя от своего родителя:

setsid()

Диссоциированный дочерний процесс не создает зомби и не отправляет SIGCHLDродительскому процессу на моем установленном экземпляре Solaris 11.2.

Это сокращенная демонизация дочернего процесса "огонь-и-забудь", делающая только то, что необходимо для предотвращения создания зомби или отправки SIGCHLDродительскому процессу. Для гораздо более полной демонизации процедуры, см. В разделе Линукс демонизации

https://stackoverflow.com/questions/46621463/detach-child-process-from-parent/46621604#comment80194748_46621604
Спасибо, вы знаете какое-нибудь решение, которое не меняет глобальное поведение в программе? Это решение изменит другие неизвестные части программы, которые могут захотеть синхронизироваться со своими детьми.
https://stackoverflow.com/questions/46621463/detach-child-process-from-parent/46621604#comment80198819_46621604
@Shaggi смотрите обновление. Вы должны иметь возможность использовать setsid()после fork()и перед execv*(), чтобы позволить дочернему процессу "скрываться" от родительского, а не создавать зомби или отправлять SIGCHLDпо завершении.
https://stackoverflow.com/questions/46621463/detach-child-process-from-parent/46621604#comment80201935_46621604
Очень мило, спасибо. Мое последнее желание состоит в том, чтобы иметь возможность сделать это от родителя на произвольном этапе жизни ребенка, но я полагаю, что это действительно невозможно.
https://stackoverflow.com/questions/46621463/detach-child-process-from-parent/46621604#comment80213352_46621604
Функция @ Shaggi setsid()безопасна для асинхронных сигналов, поэтому вы можете просто создать функцию обработчика сигналов в коде дочернего процесса, которая вызывает setsid()по выбранному вами сигналу , например SIGUSR1, или по одному из сигналов реального времени SIGRTMIN + n. Затем, когда вы хотите предотвратить отправку родительского SIGCHLD, просто вызовите kill( pid, SIGUSR1 );чтобы дочерний процесс вызвал обработчик сигнала.
Bernard

07.02.2020 12:26:26

Начиная с Python 3.2, вы можете использовать подпроцесс.Popen() и передайте start_new_session=True, чтобы выполнить это.

Состояние документов:

Если start_new_session имеет значение true, то системный вызов setsid () будет выполнен в дочернем процессе до выполнения подпроцесса. (Только POSIX)

https://docs.python.org/3/library/subprocess.html#subprocess.Popen

Обратите внимание, что это не позволяет "делать это от родителя на произвольном этапе жизни ребенка", как указано в последующем комментарии.

Закрыть X