【发布时间】:2019-11-09 15:22:34
【问题描述】:
如果我通过Ctrl-C 杀死一个Python 进程,所有子进程(由subprocess 启动)都会死掉。但是,如果我通过kill -2 杀死 Python 进程,子进程会继续运行。我认为Ctrl-C 与发送SIGINT 相同(即kill -2)。为什么行为不同?
【问题讨论】:
如果我通过Ctrl-C 杀死一个Python 进程,所有子进程(由subprocess 启动)都会死掉。但是,如果我通过kill -2 杀死 Python 进程,子进程会继续运行。我认为Ctrl-C 与发送SIGINT 相同(即kill -2)。为什么行为不同?
【问题讨论】:
python 进程及其由多进程或子进程启动的子进程都连接到同一个终端——具体来说,它们都是同一个进程组的一部分。当终端接收到 Ctrl-C 时,它会向连接到终端的所有进程发送 SIGINT,这就是为什么您会看到主 python 线程及其子线程接收到信号。
当您执行kill -2 PID 时,您将 SIGINT 发送到该进程组的特定进程;不会选择其他进程。
如果您改为使用kill -2 -PGID(注意减号和G),您将复制Ctrl-C 的操作。这指示 kill 以进程组级别的信号为目标;组内的所有进程都会收到信号。
您可以运行此命令来查看每个 python 进程的进程组 ID:
ps -o pgid,ppid,pid,lwp,sgi_p,fname,cmd -C python
... 示例输出 ....
PGID PPID PID LWP P COMMAND CMD
22706 19662 22706 22706 * python python parent.py
22706 22706 22707 22707 * python python /var/tmp/child.py
22706 22706 22708 22708 * python python /var/tmp/child.py
22706 22706 22709 22709 * python python /var/tmp/child.py
22706 22706 22710 22710 * python python /var/tmp/child.py
22706 22706 22711 22711 * python python /var/tmp/child.py
(PGID:组ID,PPID:父ID,PID:进程ID,LWP:线程ID)
...然后向整个组发送 SIGINT:
kill -2 -22706
有关 Ctrl-C 和进程组的详细说明,请参见此处:https://unix.stackexchange.com/questions/149741/why-is-sigint-not-propagated-to-child-process-when-sent-to-its-parent-process
【讨论】: