【问题标题】:SIGCHLD and fork + waitpid() in a librarySIGCHLD 和 fork + waitpid() 在一个库中
【发布时间】:2018-09-20 20:25:09
【问题描述】:

我正在编写一个使用fork()exec() 运行外部程序的库。 我的库中的代码作为单独的线程运行。 库线程需要在fork出的进程上waitpid()才能知道子进程的退出码。

不幸的是,如果使用我的库的应用程序为SIGCHLD 注册了信号处理程序,waitpid() 调用将返回错误ECHILD

作为一个对应用程序影响最小的库,我该如何处理? 我本质上希望孩子保持僵尸状态,并控制何时收割。

我可以将自己与应用程序决定做的事情隔离开来吗? 我可以以某种方式劫持信号处理程序并在我的waitpid 完成后将其放回吗?

【问题讨论】:

  • 您可以分叉您的自己的 进程来处理您自己的进程处理,并让库通过管道或IPC 之类的方式与独立进程通信。然后您还可以安装自己的信号处理程序,例如你自己的SIGCHLD 而不是只依赖waitpid
  • 第二。 Unix 域数据报套接字通常对此很有用。 Unix 域套接字允许您使用辅助消息将文件描述符(例如与分叉的孙进程之间的管道描述符)传递回父进程。 Unix 域数据报消息不会重新排序,并保留消息边界(因此具有足够大缓冲区的接收将始终接收完整消息);这些特性使通信简单而健壮。对于这种方法,您甚至可能不需要单独的线程;辅助进程就足够了。
  • 这是 Unix fork/wait 模型的一个古老问题,我不确定是否有任何简单的解决方案。
  • 是的,看起来确实是一个复杂的问题。感谢您的回复!由于我的库被一组具有已知功能的非常受控的用户使用,我只是想说“不要注册信号处理程序”。
  • 据我了解,标准的system() 函数也存在同样的问题。

标签: c linux fork waitpid


【解决方案1】:

释放由库分配的资源是一个应用程序错误。原则上与应用程序执行free(yourlib_create_context(...)) 之类的操作相同,尽管后果当然不那么严重。没有理由尝试支持这种无意义的应用程序行为;只是证明它是无效的。

如果您想“屏蔽”此类编程错误,如果waitpid 失败并返回ECHLD,则掩码会发出信号,然后调用abort。这将无条件终止进程,而应用程序没有机会捕获它。

【讨论】:

    【解决方案2】:

    您可以像system 那样做:

    system() 通过调用/bin/sh -c 命令执行command 中指定的命令,并在命令完成后返回。命令执行过程中,SIGCHLD会被阻塞,SIGINT和SIGQUIT会被忽略。

    大纲可以是

    pid_t pid;
    sigset_t block, backup;
    
    sigemptyset(&block);
    sigaddset(&block, SIGCHLD);
    
    sigprocmask(SIG_BLOCK, &block, &backup);
    
    if ((pid = fork()) < 0) {
        // error handle
    } else if (pid == 0) {    // child
        sigprocmask(SIG_SETMASK, &backup, NULL);
    
        // ...
    } else {
        // waitpid
    
        sigprocmask(SIG_SETMASK, &backup, NULL);
    }
    
    // ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-29
      • 1970-01-01
      • 2012-11-09
      • 2016-03-19
      • 1970-01-01
      • 1970-01-01
      • 2012-11-24
      相关资源
      最近更新 更多