Linux 中创建子进程是相当方便的,通过fork调用即可。当子进程退出时,要给父进程发送SIG_CHLD信号,是为了父进程回收子进程的资源,方便管理的目的。 但是当父进程退出后,一般是不会通知子进程的,父进程会将自己的所有子进程过继给init进程。
但是,在实际的项目中,我们有这样的需求: 如果父进程退出后,希望能通知子进程退出。
我们知道,可以利用进程间通信机制,在父进程退出前主动发送信号或pipe或其他手段告知子进程自己退出了。
但是,当父进程意外退出时,比如coredump了,根本没机会主动发送信号或pipe等消息的。
这时怎么办呢?
我们发现 prctl 这个调用, 通过man prctl:
PR_SET_PDEATHSIG (since Linux 2.1.57)
Set the parent process death signal of the calling process to arg2 (either a signal value in the range
1..maxsig, or 0 to clear). This is the signal that the calling process
will get when its parent dies.
据此, 我们可以在子进程中给父进程设置当父进程退出时子进程收到的信号。
prctl(PR_SET_PDEATHSIG, SIGHUP);
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <signal.h>
static int do_abort = 0;
void handle_signal(int signo)
{
if (signo == SIGHUP)
{
printf("child recv SIGHUP..\n");
do_abort = 1;
}
}
int main(void)
{
pid_t pid;
pid = fork();
char *p = NULL;
if (pid == 0) // child
{
signal(SIGHUP, handle_signal);
prctl(PR_SET_PDEATHSIG, SIGHUP);
while(!do_abort) {
sleep(1);
printf("in child...\n");
}
printf("child exit...\n");
return 0;
}
else // parent
{
int times = 5;
while(times -- > 0)
{
sleep(1);
if (times == 3)
{
printf("memcpy ...\n");
memcpy(p, "Hello", 5);
}
printf("in parent.\n");
}
printf("parent exit..\n");
return 0;
}
return 0;
}
通过测试,如果去掉 prctl调用,当父进程发生段错误退出后,子进程依然继续运行。 如果去掉signal调用,即子进程不捕获SIG_HUP信号,当父进程退出后依然会退出,只是退出的有些不优雅罢了。