我有一个简单的C程序,分叉一个进程,并调用exec来运行命令如下:
#include<stdio.h> #include<signal.h> #include<unistd.h> #include<sys/types.h> int fork_process(int sleep_interval) { char cmd[30]; pid_t pid = fork(); if (pid > 0) { return pid; } else if (pid < 0) { printf("At parent. Couldn't create a child process!\n"); return pid; } else { sprintf(cmd, "sleep %d; %s", sleep_interval, "gzip a > a.gz"); execlp("sh", "sh", "-c", cmd, (char *) 0); } } int main () { pid_t pid = fork_process(400); sleep (10); kill(pid, SIGTERM); return 1; }
当我运行这个程序的时候,我注意到sh
内部分叉一个运行sleep 400
的进程:
$ps x 1428 pts/80 S+ 0:00 ./kill_prog 1429 pts/80 S+ 0:00 sh -c sleep 400; gzip a > a.gz 1430 pts/80 S+ 0:00 sleep 400
现在,当SIGTERM
信号在程序中通过其pid(这里是1429
)发送到subprocess时,我注意到subprocess终止了,但是没有执行sleep 400
进程sleep 400
(pid 1430
)。 换句话说,执行sleep 400
的处理变成僵尸直到它完成。
如何发送一个终止信号,使信号传播到subprocess中分叉的进程? 我尝试使用kill
的进程组ID作为kill(-1*pid, SIGTERM)
但无济于事。
我终于想出了一个解决上述问题的方法。 这是一个小小的变化。
我在分岔一个孩子之后补充说:
pid_t pid = fork(); if (pid > 0) { // Make child process the leader of its own process group. This allows // signals to also be delivered to processes forked by the child process. setpgid(childpid, 0); return pid; }
最后,将信号发送给整个过程组:
// Send signal to process group of child which is denoted by -ve value of child pid. // This is done to ensure delivery of signal to processes forked within the child. kill((-1*pid), SIGTERM);
真的很简单:只要添加一个SIGTERM信号处理程序的过程: