【问题标题】:Linux system() and signal handler cause a race condition?Linux system() 和信号处理程序导致竞争条件?
【发布时间】:2014-09-23 13:08:00
【问题描述】:

我遇到了如下代码的问题:

void sighandler(int signo)
{
    printf("sighandler() called\n");

    pid_t pid;
    pid = waitpid(-1, NULL, WNOHANG);
    if(pid >= 0)
    {
        printf("Caught by sighandler(): pid = %d\n", pid);
    }
    else
    {
        perror("sighandler pid failed");
    }
}


int main(void)
{
    int ret = 0;
    pid_t pid;

    signal(SIGCHLD, sighandler);

    ret = system("ls -al");

    if(ret < 0)
    {
        perror("system failed");
        printf("return value is %d\n", ret);
    }

    return 0;
}
  1. 在Linux(Cent OS)环境下,sighandler()会在system()完成后触发。但是在 Mac OS X 上,sighandler() 不会在相同的条件下被调用。这是 Linux 和 BSD/UNIX 系统之间已知的区别吗?

  2. 真正的问题是,在 GTK(C 语言)程序中,SIGCHLD 与主例程中的sighandler() 绑定。但是后来我发现在子窗口GTK Button的回调函数中调用的system()总是返回-1。我完全确定SIGCHLD 没有与SIG_IGN 绑定,它仍然绑定sighandler()sighandler()中的waitpid是否有可能在system()中的waitpid()之前捕获死子进程,这是为了处理死子进程?

【问题讨论】:

  • 叹气,这真的很难用谷歌搜索,因为“系统”匹配“操作系统”和“系统调用”,而这些经常与“SIGCHLD”在同一页面上找到
  • @Barmar 你是绝对正确的。即使我可以通过在调用它之前将 SIGCHLD 与 SIG_DFL 绑定来使 system() 正常工作,我也花了几个小时在它上面。但这真的让我很困惑,因为我无法通过自己编写程序来重现问题:每次死进程都由 system() 本身处理并且根本没有任何问题。

标签: c linux unix gtk signals


【解决方案1】:

以下是system 的 POSIX 规范关于SIGCHLD 的内容:

system() 函数应忽略 SIGINT 和 SIGQUIT 信号,并应阻塞 SIGCHLD 信号,同时等待命令终止。

在等待子进程终止时阻塞 SIGCHLD 可防止应用程序在 system() 自己获取状态之前捕获信号并从 system() 的子进程获取状态。

请注意,如果应用程序正在捕获 SIGCHLD 信号,它将在成功的 system() 调用返回之前接收到这样的信号。

最后一点是因为当system() 解除对SIGCHLD 的阻塞时,挂起的信号被传递,并且它进入应用程序的处理程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-03
    • 2011-09-23
    • 2012-04-15
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 2014-02-23
    • 1970-01-01
    相关资源
    最近更新 更多