【问题标题】:Does a KILL signal exit a process immediately?KILL 信号是否立即退出进程?
【发布时间】:2012-01-30 13:01:00
【问题描述】:

我正在开发一个使用fork() 和 exec 来创建子进程的服务器代码。子进程的PID在fork()成功时注册,在CHILD信号被捕获时清理。

如果服务器需要停止,所有程序都会被终止,最终会发出 KILL 信号。现在,这通过遍历所有已注册的 PID 并等待 CHILD 信号处理程序删除 PID 来工作。如果子程序没有正确退出,这将失败。因此,我想将killwaitpid 结合使用,以确保清理并记录PID 列表并执行其他操作。

考虑下一个代码示例:

kill(pid, SIGKILL);
waitpid(pid, NULL, WNOHANG);

摘自waitpid(2)

waitpid():成功时,返回状态发生变化的子进程ID;如果指定了 WNOHANG 并且有一个或多个孩子 pid 指定的存在,但尚未改变状态,则返回 0。出错时返回-1。

pid 给出的进程总是在下一个函数启动之前就已经过去了吗?在上述情况下waitpid 是否总是返回-1

【问题讨论】:

  • KILL 信号相当残酷,为什么不是 INT 或 HUP?还有,kill 系统调用的返回码是什么?
  • "等待 CHILD 信号处理程序..." -- SIGKILL 没有信号处理程序,你知道吗?除 SIGSTOP 和 SIGKILL 之外的所有信号都将执行 sigaction 设置的操作(例如调用处理程序)或默认值。 SIGSTOP 只是停止,而 SIGKILL 只是终止该进程。总是。没有处理或条件。 (例外是 kill 系统调用失败,因为您没有足够的权限。)
  • @Damon: SIGKILL 不能被目标进程忽略,没错。但这不是问题/问题。源进程上的kill(2) 系统调用可以在目标进程上下文中(由内核)评估信号之前返回。 kill(2) 基本上是一个非常简单的异步通信,必须按照所有含义进行处理。
  • 是的,除非别无选择,否则不要使用SIGKILL。如果要指示进程终止,请使用SIGTERM
  • @fge 如果孩子在 SIGTERM 上响应不够快,它最终发送 SIGKILL。

标签: c linux signals


【解决方案1】:

pid 给出的进程总是在下一个函数启动之前就消失了吗?

对此没有任何保证。在多处理器上,您的进程可能在 CPU 0 上,而内核中对被杀死进程的清理发生在 CPU 1 上。这是典型的竞争条件。即使在单核处理器上也无法保证。

在上述情况下,waitpid 总是返回 -1 吗?

因为它是一个竞争条件 - 在大多数情况下它可能会。但不能保证。


由于您对状态不感兴趣,因此此半码可能更适合您的情况:

// kill all childs
foreach(pid from pidlist)
    kill(pid, SIGKILL);

// gather results - remove zombies
while( not_empty(pidlist) )
    pid = waitpid(-1, NULL, WNOHANG);
    if( pid > 0 )
        remove_list_item(pidlist, pid);
    else if( pid == 0 )
        sleep(1);
    else
        break;

【讨论】:

  • 感谢您的解释,我将无法使用建议的代码,因为 SIGCHILD 处理程序会从 pidlist 中删除项目。这让我可以选择:检查进程是否正在运行,如果没有则删除,否则终止。
  • 只需删除 WNOHANG 标志,您的代码就会按预期工作。
  • @Lekensteyn:如果已经有一个更新列表的 SIGCHLD 处理程序,那么这个处理程序可以调用waitpid 来删除僵尸进程。然后while 循环只需要等待a)所有进程都死掉和埋没或b)安全超时。
【解决方案2】:

KILL 信号处理程序将在被杀死的进程 CPU 时间内运行。这可能比您的 waitpid 调用晚得多,尤其是在已加载的系统上,因此 waitpid 可以很好地返回 0。

【讨论】:

    【解决方案3】:

    JFYI 还有pidfd_send_signal() 的选项。来自手册:

    pidfd_send_signal() 系统调用允许避免竞争 使用传统接口时出现的情况(例如 kill(2)) 向进程发出信号。问题是, 传统接口通过进程指定目标进程 ID (PID),结果发送者可能不小心发送了一个 如果最初预期的目标,则向错误的进程发出信号 进程已终止且其 PID 已被回收用于另一个进程 过程。相比之下,PID 文件描述符是一个稳定的 参考特定过程;如果该过程终止, pidfd_send_signal() 失败并出现错误 ESRCH。

    您可以查看一个有关如何使用它的示例here

    【讨论】:

      猜你喜欢
      • 2013-07-28
      • 2022-07-08
      • 1970-01-01
      • 2012-01-18
      • 1970-01-01
      • 2012-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多