在我的程序中,我正在收听传入的SIGCHLD信号,以避免僵尸。
代码:
void myhandler(int signo)
{
printf("test");
int status;
pid_t pid;
while((pid = waitpid(-1, &status, WNOHANG)) > 0)
++count;
}
int main(int argc, char const *argv[])
{
struct sigaction sigchld_action;
memset(&sigchld_action,0,sizeof(sigchld_action));
sigchld_action.sa_handler = &myhandler;
sigaction(SIGCHLD,&sigchld_action,NULL);
if(fork() == 0){
exit(0);
}
if(fork()==0){
exit(0);
}
if(fork()==0){
exit(0);
}
while(wait(NULL) > 0)
++count;
return 0;
}问题是,分叉子数和printf输出数(“test”)有时不匹配。分叉儿童的数量大于数字printf("test")。
这个代码段是否保证不会有僵尸?如果是的话,它如何才能做到这一点?它没有打印正确的“测试”号。在这段时间内,waitpid()是否不止一次清除死去的孩子?
当这个信号处理程序调用时,会发生什么,同时会有另一个孩子死亡。默认情况下,信号将被阻塞。(当处理程序正在运行时,另一个子程序可能会死)。在信号处理程序运行时,等待程序是否清除其发送信号的进程?
而且,计数器是不相等的。(静态易失性int)或我尝试了原子整数。
发布于 2020-04-19 19:09:10
正在发生两件不同的事情:
printf并不是异步信号安全的,所以您不应该从信号处理程序调用它。用write.count。如果您想知道有多少进程死亡,则需要在while循环中增加它。。
试试下面的代码:
void handler(int signo)
{
int status;
pid_t pid;
while((pid = waitpid(-1, &status, WNOHANG)) > 0) {
write(1, "test", 4); /* technically this may result in a partial write and you should loop it, but in practice I think this'll be fine for this example */
++count;
}
}使用该代码,您可能没有僵尸,test的数量和count中的值都是正确的。但是,还有一个争用条件:如果在对waitpid的最后调用与信号处理程序的结束之间,另一个子进程死亡,那么将不会接收到SIGCHLD,因此它将是一个僵尸,直到它死后的那个。这种边缘情况的解决方案要复杂得多,这取决于您的应用程序的其余部分是如何构造的。
https://stackoverflow.com/questions/61308373
复制相似问题