首页 文章

在waitpid中处理SIG_CHLD

提问于
浏览
0

我尝试使用以下(Will wait and waitpid block SIGCHLD and unblock it when they return in Linux?)来回答我的问题 . 链接的解决方案让我了解下面的理解 . 那为什么会弄错?


鉴于以下内容:

  • 处理程序
void sig_child(int sig)
{
signal(SIGCHLD, sig_child);

if (sig == SIGCHLD)
{
    int status;
    pid_t num;
    while ((num = waitpid(WAIT_ANY, &status, WNOHANG)) > 0)
    {

    }
    if (num == -1 && errno != ECHILD)
    {
        // We shouldn't reach here
        assert(0);
    }

}

主要的模糊:

if (pidnum)
           {  //Some work
                int status;
                pid_t num = waitpid(pidnum, &status, 0);
               // Some work
            }

我认为应该发生以下情况:

1)主代码(在第二个模糊中)调用waitpid

2)引发SIG_CHLD,因此控制转移到信号处理程序

3)信号处理程序从信号处理程序中删除已终止的子进程,获取其状态信息

4)当控制转回主代码(第二个模糊)时,由于进程的子进程已从进程表中删除,因此num应设置为-1


实际上,发生了以下情况(我使用了一些现在被删除以跟踪流程的打印语句),这与我上面的理解相矛盾:

1)主要的模糊到达waitpid

2)引发SIG_CHLD,因此控制转移到处理程序

3)num设置为-1,errno设置为ECHILD

4)控制返回到主模糊,其中num被赋予之前分叉的孩子的pid .

1 回答

  • 0

    你正在做两个具有重叠标准的 waitpid ,抱怨一个人 grab 了你的过程而另一个人认为没有办法解决这个特殊情况 .

    我看到它的方式,你有两个解决方案的途径 . 一种是使用不重叠的 waitpid 标准 . 问题是,很难看出如何创建这样的案例 .

    更合理的解决方案是在主循环中只有一个 waitpid . 等待检查报告的pid,并以两种不同的方式处理它 . 如果它是主程序的孩子,做一件事 . 如果它是您正在运行的后台任务之一,请执行另一个(或者,在您的情况下,不执行任何操作) .

    如果你不能,无论出于何种原因,在主循环内部处理后台进程的退出时,只需在执行主等待时阻止 SIGCHLD .

    在任何情况下,请始终牢记 SIGCHLD 是一个非排队信号 . 这意味着您永远无法确保调用信号处理程序的次数与运行的 wait 次数之间存在1:1的关系 .

相关问题