2015-12-03 100 views
3

添加信号处理程序,例如如何注册子进程的信号处理程序?

#!/usr/bin/python 

import subprocess as sp 
import signal 
import time 

def child_handler(sig, frame): 
    print("SIGINT child received") 

def handler(sig, frame): 
    print("SIGINT received") 

def preexec(): 
    print("entering preexec") 
    signal.signal(signal.SIGINT, child_handler) 
    #signal.signal(signal.SIGINT, signal.SIG_IGN) 
    print("leaving preexec") 

def signal_sending(): 
    signal.signal(signal.SIGINT, handler) 
    p = sp.check_call(["bash", "process.sh"], preexec_fn=preexec) 

if __name__ == "__main__": 
    signal_sending() 

process.sh

#!/bin/sh 

i=0 

while [ 1 ]; do 
sleep 0.1; 
echo $i 
i=$((i + 1)) 
done 

不起作用,因为按Ctrlç中断子进程(仅SIGINT received打印),但两者SIGINT receivedSIGINT child received应打印和孩子继续跑步。

添加signal.SIG_IGN离开孩子也不放过,但还不够,因为我需要写为孩子定制的处理程序。

我不在乎,如果我有使用Python 2.7或3.x版到acchieve这一点。我正在使用Linux 4.3。

回答

1

bash过程取代了分叉python过程,因此它不能运行Python回调。 SIG_IGN适用于SIGINT,因为它在exec()电话中生存。

如果你想要一些Python代码运行时Ctrl + C被按下;把它放在handler()(父母的信号处理程序)。或者在bash中捕获相应的信号,然后在process.sh的信号上运行python子进程。

+0

啊,我只是要求对信号处理的更好的文档在http://bugs.python.org/issue25787。任何想法如何防止接收子进程的子进程的SIGINT?我很忙于'apt-get',它产生'dpkg',它自己产生像'gpgv'这样的进程,并且因为SIGINT被儿童的孩子接收而中止。 –

+0

shell中的Ctrl + C将SIGINT发送到前台进程组(当前管道)中的所有进程。通过'preexec_fn = os.setpgrp'来创建一个新的进程组,以避免信号传播给子进程(及其子进程)。 – jfs

+0

指定'preexec_fn = os.setpgrp'使终端('侏儒-terminal'和'xterm')无响应期待'其在父进程处理(在我的注册自定义处理程序)SIGINT'。 –

相关问题