为什么我不能用 SIGTERM 杀死一个 SIGSTOP 的进程,挂起的信号存储在哪里?

noh*_*hup 26 process kill signals

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

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

roa*_*ima 43

SIGSTOPSIGKILL是无法被进程捕获和处理的两个信号。SIGTSTP就像SIGSTOP可以被捕获和处理。

SIGSTOPSIGTSTP在其轨道的信号停止一个进程,准备好SIGCONT。当您发送该进程 a 时SIGTERM,该进程没有运行,因此它无法运行代码退出。

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

CtrlZ发送的进程 aSIGTSTP似乎没有以任何方式特别处理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
Run Code Online (Sandbox Code Playgroud)

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

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

  • @nohup 是的,根据文档:« _当一个进程停止时,在它继续之前不能再向它传递信号......信号被标记为挂起,但在进程继续之前不会传递。_ » (2认同)
  • @coteyr。我不同意:`SIGKILL` 会阻止应用程序清理,因此在许多(大多数)情况下最好使用 `SIGTERM`。 (2认同)

ilk*_*chu 10

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

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

  • 抱歉,我之前的评论是错误的。当进程停止时,除了 SIGKILL 和 SIGCONT 之外,不会向它传递任何信号。即使该信号具有终止进程的默认操作,也会延迟到进程被 SIGCONT 恢复。POSIX 强制执行此行为。 (4认同)