为什么我不能使用 SIGTERM 终止 SIGSTOP 进程,挂起的信号存储在哪里?

为什么我不能使用 SIGTERM 终止 SIGSTOP 进程,挂起的信号存储在哪里?

我正在使用 Debian Stretch (systemd)。我在前台运行 rsyslog 守护进程, /usr/sbin/rsyslogd -n 并使用Ctrl+Z来停止它。进程的状态更改为Tl(已停止,已线程化)。我向该进程发出了多个命令,并且该进程的状态是相同的:。一旦我做了,它就死了。我有 3 个问题。kill -15 <pid>Tlfg

  • 为什么SIGSTOP-ed 进程没有响应SIGTERM?为什么内核保持它处于相同的状态?
  • 为什么它一收到SIGCONT信号就被杀了?
  • 如果是因为之前的SIGTERM信号,那么在进程恢复之前它会保存在哪里?

答案1

SIGSTOPSIGKILL是进程无法捕获和处理的两个信号。SIGTSTP就像SIGSTOP除了它被抓住并处理。

SIGSTOP和信号SIGTSTP停止进程,为 做好准备SIGCONT。当您向该进程发送 a 时SIGTERM,该进程未运行,因此无法运行代码来退出。

(还有 和SIGTTINSIGTTOU它们是当后台作业尝试读取或写入终端时由 TTY 层生成的信号。它们可以被捕获,但否则会停止(挂起)进程,就像 一样SIGTSTP。但我现在要在这个答案的其余部分忽略这两个。)

CtrlZ发送进程 a SIGTSTP,该进程似乎没有以任何方式进行特殊处理rsyslogd,因此它只是挂起进程挂起SIGCONTSIGKILL

这里的解决方案也是SIGCONT在你之后发送SIGTERM,以便进程可以接收和处理信号。

例子:

sleep 999 &

# Assume we got PID 456 for this process
kill -TSTP 456    # Suspend the process (nicely)
kill -TERM 456    # Terminate the process (nicely). Nothing happens
kill -CONT 456    # Continue the process so it can exit cleanly

的文档GNU C 库我认为(我的重点)很好地解释了这一点:

当进程停止时,在进程继续运行之前,无法再向其传递任何信号,除了SIGKILL信号和(显然)SIGCONT信号。信号被标记为待处理,但在进程继续之前不会传递。SIGKILL信号总是导致进程终止,并且不能被阻止、处理或忽略。您可以忽略SIGCONT,但如果进程停止,它总是会导致进程继续运行。SIGCONT向进程发送信号会导致该进程的任何挂起的停止信号被丢弃。同样,SIGCONT当进程收到停止信号时,该进程的任何待处理信号都会被丢弃

答案2

SIGTERM和其他的一样信号在那里面它可以被抓住通过一个过程。接收信号只会使进程跳转到特殊的信号处理程序例程。默认SIGTERM操作是终止进程,但例如编辑器可能希望捕获信号,以便它可以在死亡之前保存任何打开文件的草稿副本。如果进程停止,则无法运行信号处理程序,但信号将保持挂起状态,直到进程继续。请注意,数字发送的信号通常不会被保存。

理论上,系统可以知道该进程是否安装了信号处理程序SIGTERM,如果没有,则立即终止它。但是(根据 Gilles 的评论)POSIX 要求信号将挂起,直到进程通过 继续SIGCONT

相关内容