В Linux вы можете установить родительский сигнал смерти ребенка, например ::10000
#include <sys/prctl.h> // prctl(), PR_SET_PDEATHSIG
#include <signal.h> // signals
#include <unistd.h> // fork()
#include <stdio.h> // perror()
// ...
pid_t ppid_before_fork = getpid();
pid_t pid = fork();
if (pid == -1) { perror(0); exit(1); }
if (pid) {
; // continue parent execution
} else {
int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
if (r == -1) { perror(0); exit(1); }
// test in case the original parent exited just
// before the prctl() call
if (getppid() != ppid_before_fork)
exit(1);
// continue child execution ...
Обратите внимание, что сохранение идентификатора родительского процесса до разветвления и его тестирование в дочернем процессе после prctl()
устраняет условие гонки между prctl()
и выходом из процесса, называется ребенок.
Также обратите внимание, что родительский сигнал смерти ребенка очищается у вновь созданных детей самостоятельно. На него не влияет execve()
.
Этот тест может быть упрощен, если мы уверены, что системный процесс, отвечающий за принятие всех сирот , имеет PID 1:
pid_t pid = fork();
if (pid == -1) { perror(0); exit(1); }
if (pid) {
; // continue parent execution
} else {
int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
if (r == -1) { perror(0); exit(1); }
// test in case the original parent exited just
// before the prctl() call
if (getppid() == 1)
exit(1);
// continue child execution ...
Однако полагаться на то, что системный процесс init
и имеет PID 1, нельзя переносить. POSIX.1-2008 указывает :
Идентификатор родительского процесса всех существующих дочерних процессов и процессов-зомби вызывающего процесса должен быть установлен равным идентификатору процесса, определяемого реализацией системного процесса. То есть эти процессы должны наследоваться специальным системным процессом.
Традиционно системный процесс, принимающий всех сирот, - это PID 1, то есть init - предок всех процессов.
В современных системах, таких как Linux или FreeBSD , эту роль может выполнять другой процесс. Например, в Linux процесс может вызвать prctl(PR_SET_CHILD_SUBREAPER, 1)
, чтобы установить себя как системный процесс, который наследует всех сирот любого из его потомков (см. пример в Fedora 25).