c - 将 SA_NOCLDWAIT 设置为 SIGCHLD 后的 Linux system()

标签 c linux process signals

system() 的手册页 states “在执行命令期间,SIGCHLD 将被阻止”
在我的代码中,我正在为 SIGCHLD 安装一个处理程序,它向日志中写入一些内容并忽略该信号。我这样做是为了了解在我的日志中退出的子进程并避免僵尸进程。

当我使用 system() 调用时出现问题。有了这个处理程序 system() 总是返回 -1 而不是 child 的退出代码。但根据手册页中的上述引述,system() 应该处理来自子进程的信号。

我做错了什么?

我的代码如下:

static void handleSignal(int signum, siginfo_t* inf, void* ctx) {
    cout << "in signal " << signum << endl;
}

int main() {
    struct sigaction chldsa, prevchld;
    chldsa.sa_sigaction = &handleSignal;
    sigemptyset(&chldsa.sa_mask);
    chldsa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NOCLDSTOP | SA_NOCLDWAIT;
    if (sigaction(SIGCHLD, &chldsa, &prevchld) == -1) {
        cout << "Failed setting sigaction SIGCHLD " << errno;
    }

    int x = system("exit 1");
    cout << "RET=" << x << endl;
}

最佳答案

如果您想摆脱SA_NOCLDWAIT及其影响,只需在您的结尾收割所有 child SIGCHLD 处理程序。

编辑添加:刚刚验证了以下内容:

    pid_t p;

    /* Reap all pending child processes */
    do {
        p = waitpid(-1, NULL, WNOHANG);
    } while (p != (pid_t)0 && p != (pid_t)-1);

最后在 SIGCHLD 处理程序中运行时工作正常(已安装 SA_NOCLDSTOP |SA_RESTART | SA_SIGINFO)。没有僵尸,system() 返回正确的退出状态。

请注意 waitpid()是一个 async-signal safe Linux 中的函数,根据 POSIX.1-2004,WNOHANG 表示调用永远不会阻塞,因此上述循环是安全的。

但是,由于标准信号没有排队,如果两个或多个进程在正确的时间退出,其中一个在您的父进程中执行 child-reaping 循环之后但在信号处理程序返回之前退出是可能的,一个或多个 child 不会立即收割。但是,当下一个子进程退出时,它们会。为了缓解这种情况,您应该定期运行上述循环,作为程序正常运行的一部分,或者通过定时器中断。循环从不阻塞,消耗的 CPU 时间非常少。

请记住,waitpid(-1, NULL, WNOHANG) 将返回零,如果有活着的 child ,-1errno == ECHILD 如果没有活着的 child ,或者刚刚收割的进程的进程 ID。 (如果你愿意,你可以在你的日志记录中使用循环,使用一个非 NULL 状态指针来捕获每个已经退出的 child 的退出状态,并记录它。你甚至可以将一个周期性计时器挂接到同一个信号处理程序,例如。)

关于c - 将 SA_NOCLDWAIT 设置为 SIGCHLD 后的 Linux system(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17532632/

相关文章:

c - 为什么打印结构变量会给出第一个元素的值?

c - 在 gtk 中显示来自互联网的图像

linux - 查看其他应用程序创建的现有套接字上的套接字选项?

javascript - 为什么 Node 的 process.stdin.on ('readable' ) 会触发我的回调一次?

linux - 退出状态代码 4479

process - 为什么erlang中使用 'monitor'选项:spawn_opt disabled?

c - 从用户那里读取号码

c - 验证输入并清除键盘缓冲区

c - 为什么主机系统上的 lua 比 linux vm 上的慢?

linux - 在不使用 root 的情况下通过 ssh 备份远程服务器