【问题标题】:SIGCHLD handler in c - unwanted waitc 中的 SIGCHLD 处理程序 - 不需要的等待
【发布时间】:2012-11-19 13:53:33
【问题描述】:

我的 SIGCHLD 处理函数存在以下问题。

处理程序代码非常简单:

void sigchld_handler(int signum)
{
    pid_t ended;    
    signal(SIGCHLD, sigchld_handler);
    ended = wait(NULL);
    // do some stuff with the PID of the finished child process
}

当我只 fork 一个孩子时,这很有效。如果我有 2 个孩子(或更多)并且其中一个已完成运行,则 sigchld_handler() 将启动,当它到达“ended = wait(NULL)”行时,程序会一直等到我拥有的另一个孩子完成。

有没有办法获取刚刚以不同方式结束的孩子的 PID 并避免这种等待?

【问题讨论】:

  • 为什么在信号处理程序中调用signal()
  • 不确定我理解你的意思。我使用第 2 行的 signal() 来保存其他进程的设置,它没有进一步的用途。 “做一些事情”不相关,也没有再次调用 signal()。
  • “保存其他进程的设置”是什么意思?只有父进程接收到信号,我觉得这里完全没有作用。
  • @mux:如果您使用signal() 而不是sigaction(),那么(对于许多信号)在调用信号处理程序之前,信号处置会自动设置为SIG_DFL。设置信号处置以便调用处理程序可能是必要的。您需要仔细检查手册页; signal() 有不同的实现——例如,BSD 有“可靠的信号”。
  • @JonathanLeffler 是的,但他在信号处理程序中再次调用signal(),它被 POSIX 指定为安全函数,所以我想这没关系,但我不知道为什么?

标签: c signals sigchld


【解决方案1】:

改用sigaction(),处理程序将具有此签名:

void (*sa_sigaction)(int, siginfo_t *, void *);

并且它在struct siginfo_t 中传递了您想要的信息,来自手册页:

SIGCHLD填写si_pid、si_uid、si_status、si_utime和si_stime, 提供有关孩子的信息。 si_pid 字段是 子进程ID

注意:当然,你仍然需要在子进程上wait(),除非你使用SA_NOCLDWAIT

【讨论】:

  • AFAIK,您仍然需要调用waitpid()wait() 以确保您的进程不会积累僵尸。
  • @JonathanLeffler 对,除非使用SA_NOCLDWAIT,否则我只是在回答有关获取子 pid 的部分。
猜你喜欢
  • 2019-08-04
  • 2018-02-20
  • 1970-01-01
  • 1970-01-01
  • 2021-01-23
  • 1970-01-01
  • 2014-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多