我正在尝试学习如何处理信号。在我的程序中,我有一组早期创建的子进程的 pid。不,我想每隔几秒钟向其中一个发送一个 sigtstp 信号。他只需要将 sigchld 发送到父进程并退出。父进程应该打印退出进程的退出代码,并在退出进程的位置创建下一个。在第一个循环中一切正常,但在第二个循环中挂起。所以输出得到:
loop
slept
forking
in to array
loop
Zakonczyl sie potomek 3934 z kodem 0.
所以看起来 sleep 在第一个循环中有效,但在第二个循环中无效。或者只是主进程在处理信号后没有取回控制权,但这不应该发生。所以我不知道这里可能出了什么问题。
while(1) {
printf("loop\n");
sleep(5);
printf("slept\n");
int r = rand() % n;
if(kill(process_tab[r],SIGTSTP) < 0) {
printf("Error while sending sigtstp signal.\n");
} else {
printf("forking\n");
if((child = fork()) < 0) {
printf("Fork failed.\n");
} else if(child == 0) {//to sie dzieje w procesie
if(signal(SIGTSTP,&catch_sigtstp)) {
printf("Error while setting signal handler.\n");
_exit(EXIT_FAILURE);
}
while(1) {
}
} else { //to sie dzieje w parencie
process_tab[r] = child;
printf("in to array\n");
}
}
}
这里是处理程序。
void catch_sigtstp(int signal) {
kill(ppid,SIGCHLD);
_exit(EXIT_SUCCESS);
}
void catch_sigchld (int signal) {
int status;
pid_t child = wait(&status);
printf("Zakonczyl sie potomek %d z kodem %d.\n",child,status);
}
最佳答案
在printf
之后添加fflush
printf("Something\n");
fflush(stdout);
否则您可能无法获得输出,因为 stdio
默认情况下是缓冲的。
编辑:处理程序问题
在信号处理程序中使用 printf
函数是非常不安全的,因为它是不可重入的。此外,可以修改 catch_sigchild
函数:
void catch_sigchld (int signal) {
int status;
pid_t child;
while ((child = waitpid(-1, &status, WNOHANG)) > 0)
{
// may be something else?
// ...printf("Zakonczyl sie potomek %d z kodem %d.\n",child,status);
}
}
原因是一个信号可以传递给多个死去的 child 。
编辑:打印时屏蔽信号。
为了避免 stdio 内部的死锁,你应该阻塞信号:
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGCHILD);
...
sigprocmask(SIG_BLOCK, &set, NULL);
printf("my output");
sigprocmask(SIG_UNBLOCK, &set, NULL);
...
编辑:正如@Barmar 指出的那样,您的父进程将收到两次 SIGCHILD 信号:一次来自您的子信号处理程序,一次来自操作系统。
要修复,移除您自己的信号源可能就足够了:
void catch_sigtstp(int signal) {
// kill(ppid,SIGCHLD); //< This one causes two signals per one child
_exit(EXIT_SUCCESS);
}
关于c - 带 sleep() 的挂环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16346261/