首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用SIGCHLD处理僵尸

用SIGCHLD处理僵尸
EN

Stack Overflow用户
提问于 2020-04-19 17:09:03
回答 1查看 518关注 0票数 0

在我的程序中,我正在收听传入的SIGCHLD信号,以避免僵尸。

代码:

代码语言:javascript
复制
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)或我尝试了原子整数。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-19 19:09:10

正在发生两件不同的事情:

  1. printf并不是异步信号安全的,所以您不应该从信号处理程序调用它。用write.
  2. You're替换它,只在信号处理程序中增加一次count。如果您想知道有多少进程死亡,则需要在while循环中增加它。

试试下面的代码:

代码语言:javascript
复制
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,因此它将是一个僵尸,直到它死后的那个。这种边缘情况的解决方案要复杂得多,这取决于您的应用程序的其余部分是如何构造的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61308373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档