【发布时间】:2016-02-17 14:52:04
【问题描述】:
我有以下简单的 python 脚本:
import os, subprocess,signal,sys
import time
out = None
sub = None
def handler(signum,frame):
print("script.py: cached sig: %i " % signum)
sys.stdout.flush()
if sub is not None and not sub.poll():
print("render.py: sent signal to prman pid: ", sub.pid)
sys.stdout.flush()
sub.send_signal(signal.SIGTERM)
sub.wait() # deadlocks....????
#os.kill(sub.pid, signal.SIGTERM) # this works
#os.waitpid(sub.pid,0) # this works
for i in range(0,5):
time.sleep(0.1)
print("script.py: cleanup %i" % i)
sys.stdout.flush()
sys.exit(128+signum)
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGUSR2, handler)
signal.signal(signal.SIGTERM, handler)
sub = subprocess.Popen(["./doStuff.sh"], stderr = subprocess.STDOUT)
sub.wait()
print("finished script.py")
doStuff.sh
#!/bin/bash
function trap_with_arg() {
func="$1" ; shift
for sig ; do
trap "$func $sig" "$sig"
done
}
pid=False
function signalHandler() {
trap - SIGINT SIGTERM
echo "doStuff.sh chached sig: $1"
echo "doStuff.sh cleanup: wait 10s"
sleep 10s
# kill ourself to signal calling process we exited on SIGINT
kill -s SIGINT $$
}
trap_with_arg signalHandler SIGINT SIGTERM
trap "echo 'doStuff.sh ignore SIGUSR2'" SIGUSR2
# ignore SIGUSR2
echo "doStuff.sh : pid: $$"
echo "doStuff.sh: some stub error" 1>&2
for i in {1..100}; do
sleep 1s
echo "doStuff.sh, rendering $i"
done
当我发送在终端中启动的进程时
python3 scripts.py &
带有kill -USR2 -$! 的信号
该脚本捕获 SIGINT,并在 sub.wait() 中永远等待,ps -uf 显示以下内容:。
user 27515 0.0 0.0 29892 8952 pts/22 S 21:56 0:00 \_ python script.py
user 27520 0.0 0.0 0 0 pts/22 Z 21:56 0:00 \_ [doStuff.sh] <defunct>
请注意doStuff.sh 正确处理 SIGINT 并退出。
我还想在调用handler 时获得stdout 的输出?如何正确执行此操作?
非常感谢!
【问题讨论】:
-
我无法重现该行为(您的操作系统、shell、python 版本是什么?)。你能提供一个虚拟的
dostuff.py作为例子吗?为什么用-$!而不是$!——前者可能会向整个进程组发送信号? -
我发送到整个进程组,因为我在集群上运行它,它向整个进程组发送 SIGUSR2 信号。
-
我更新了答案,并提供了 doStuff.sh。你能在你的机器上试试这个吗,在我的这个死锁上给出如上所示的进程列表输出
-
我更新了the minimal example 以证明
child.wait()挂在信号处理程序中。您问题中的代码也挂起(出于同样的原因)。
标签: python python-3.x subprocess signals