以下程序会重新启动一个反复运行“/ bin / sleep 10”的子项。父级为SIGINT安装一个信号处理程序,它将SIGINT传递给子级。但是,有时向孩子发送SIGINT失败。为什么会这样,我会错过什么?
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
pid_t foreground_pid = 0;
void sigint_handler(int sig)
{
printf("sigint_handler: Sending SIGINT to process %d\n",
foreground_pid);
if ((foreground_pid != 0) && kill(foreground_pid, SIGCONT) == -1) {
perror("sending SIGINT to forground process failed");
printf("foreground_pid == %d", foreground_pid);
exit(EXIT_FAILURE);
}
foreground_pid = 0;
}
int main(int argc, const char *argv[])
{
while (1) {
pid_t child_pid;
if ((child_pid = fork()) == -1) {
perror("fork failed");
exit(EXIT_FAILURE);
}
if (child_pid) { /* parent */
foreground_pid = child_pid;
printf("waiting for child (%d) to complete ...\n", child_pid);
fflush(stdout);
/* install SIGINT signal handler */
struct sigaction sa;
struct sigaction old_handler;
sa.sa_handler = sigint_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_RESETHAND;
sigaction(SIGINT, &sa, NULL);
int status = 0;
/* wait for child to finish */
if (waitpid(child_pid, &status, 0) == -1) {
perror("waitpid failed");
exit(EXIT_FAILURE);
}
printf(" done.\n");
fflush(stdout);
}
else { /* child */
char * const argv[] = { "/bin/sleep", "10", NULL};
if (execve(argv[0], argv, NULL) == -1) {
perror("execve failed");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
}
return EXIT_SUCCESS;
}
% make && ./foo
gcc -Wall -pedantic -std=c99 -D_POSIX_C_SOURCE=200809L foo.c -o foo
waiting for child (4582) to complete ...
^Csigint_handler: Sending SIGINT to process 4582
done.
waiting for child (4583) to complete ...
^Csigint_handler: Sending SIGINT to process 4583
sending SIGINT to forground process failed: No such process
foreground_pid == 4583
答案 0 :(得分:6)
当您键入 Ctrl + C 时,tty驱动程序会对整个进程组执行SIGINT
;这包括子进程,它将响应它而退出,因为它没有安装处理程序。因此,您正在复制已经完成的工作,以及当父级尝试kill()
时孩子是否还在,这是一个废话。