【问题标题】:Should I be worried about the order, in which processes in a process goup receive signals?我应该担心进程组中的哪些进程接收信号的顺序吗?
【发布时间】:2026-02-21 20:50:01
【问题描述】:

我想通过向其中的进程发送SIGTERM 来终止进程组。这可以通过kill 命令来完成,但我发现的手册中几乎没有提供关于它是如何工作的详细信息:

   int kill(pid_t pid, int sig);
   ...
   If pid is less than -1, then sig is sent to every  process  in
   the process group whose ID is -pid.

但是,信号将按什么顺序发送到组成组的进程?想象一下以下情况:在组中的主从进程之间设置了一个管道。如果在处理kill(-pid) 期间从机被杀死,而主机仍然没有,主机可能会将其报告为内部故障(在收到子机已死亡的通知后)。但是,我希望所有进程都明白这种终止是由它们的进程组外部的东西引起的。

如何避免这种混淆?我应该做的不仅仅是kill(-pid,SIGTERM)吗?或者它是由我不知道的操作系统的底层属性解决的?

注意我不能修改组内进程的代码!

【问题讨论】:

    标签: linux process signals


    【解决方案1】:

    即使所有不同种类的 UNIX 都承诺以特定顺序传递信号,调度程序仍可能决定在父代码之前运行关键的子进程代码。

    即使您的 STOP/TERM/CONT 序列也会受到此攻击。

    恐怕您可能需要更复杂的东西。也许子进程可以捕获 SIGTERM 然后循环直到它的父进程在它自己退出之前退出?如果您这样做,请务必添加超时。

    【讨论】:

    • 我无法更改我杀死的进程的代码。抱歉,已编辑问题。
    【解决方案2】:

    未经测试:使用共享内存并放入某种“我们快死了”的信号量,可以在将 I/O 错误视为真正错误之前对其进行检查。 mmap() 与 MAP_ANONYMOUS|MAP_SHARED 并确保它在您的 fork()ing 进程中存活下来。

    哦,请务必使用 volatile 关键字,否则您的信号量将被优化掉。

    【讨论】:

    • 再一次,我不能修改任何进程。如果可以的话,生活会容易得多...编辑问题以反映这一点。
    【解决方案3】:

    尝试分三步进行:

    kill(-pid, SIGSTOP);
    kill(-pid, SIGTERM);
    kill(-pid, SIGCONT);
    

    第一个 SIGSTOP 应该将所有进程置于停止状态。他们无法捕捉到这个信号,所以这应该停止整个进程组。

    SIGTERM 将排队等待进程,但我不相信它会被传递,因为进程已停止(这是来自内存,我目前无法找到参考,但我相信这是真的)。

    SIGCONT 将再次启动进程,允许传递 SIGTERM。如果从服务器首先获得 SIGCONT,主服务器可能仍会停止,因此它不会注意到从服务器离开。当master得到SIGCONT后,后面会跟着SIGTERM,终止它。

    我不知道这是否真的有效,它可能取决于所有信号何时被实际传递(包括 SIGCHLD 到主进程),但它可能值得一试。

    【讨论】:

    • 是的,这个解决方案是我目前实施的。我检查了我系统上的SIGTERM 处理程序确实没有被调用,直到进程由于SIGCONT 而唤醒。我的实验还表明,所有正确的SIGCHLD 信号都会传递给控制进程:在停止、恢复和终止我们向其发送信号的子进程时。
    • 检查ps 输出或/proc/<pid>/stat 以检查进程状态,这也表示停止状态(根据手册页,ps 中的T 输出)
    【解决方案4】:

    我的理解是,您不能依赖任何特定的信号传递顺序。

    如果您只向主进程发送 TERM 信号,然后让主进程杀死其子进程,则可以避免此问题。

    【讨论】:

    • 我不能“让”主人做任何事情。假设其来源不可用。实际上,this 就是我的问题出现的原因。 :-)
    • @Pavel Shved - 那么这真的是一个编程问题吗?据我所知,Marius 是对的,但在 ServerFault 上询问可能是值得的。系统管理员类型喜欢这类问题。 :)
    • @Duck,这肯定是一个编程问题,但是,也许服务器故障用户对此了解更多,谢谢您的指点。
    最近更新 更多