为什么不触发Python信号处理程序?

时间:2018-09-23 00:27:03

标签: python python-2.7 signals

在下面的代码片段中,我通过调用signal.signal注册了信号处理程序。但是,尽管该进程在超时后被终止,但处理程序中的printsystem语句并未执行。我究竟做错了什么?我在64位Ubuntu 18.04上运行Python 2.7.15rc1。

import signal
import time
import os
import multiprocessing as mp

def handler(signal, frame):
    print "Alarmed"
    os.system('echo Alarmed >> /tmp/log_alarm')

def launch():
    signal.signal(signal.SIGALRM, handler)
    signal.alarm(5)
    print "Process launched"
    os.execv('/bin/cat', ['cat'])
    print "You should not see this"

p = mp.Process(target=launch)
p.start()
print "Process started"
p.join()

1 个答案:

答案 0 :(得分:1)

您当时不在Python领域。 os.execv()最终导致进行execve(2)系统调用,并且其手册页指出:

  

在execve()期间保留所有进程属性,但    以下:

     
      
  • 被捕获的任何信号的处理均重置为   默认(signal(7))。
  •   
     

...

这确实是有道理的,在注册旧的处理程序时,您真的不希望运行一些新代码(也不知道这怎么可能工作,因为处理程序也会被替换)。


如果您在python中实现了cat样的行为,但没有execve一个新进程,那么它(或多或少)会按照您期望的方式工作:

import signal
import time
import os
import sys
import multiprocessing as mp

def handler(signal, frame):
    print "Alarmed"
    os.system('echo Alarmed >> /tmp/log_alarm')
    sys.exit(0)

def launch():
    signal.signal(signal.SIGALRM, handler)
    signal.alarm(5)
    print "Process launched"
    stdin = os.fdopen(0)
    stdout = os.fdopen(1, 'w')
    line = stdin.readline()
    while line:
        stdout.write(line)
        line = stdin.readline()
    print "You may end here if EOF was reached before being alarmed."

p = mp.Process(target=launch)
p.start()
print "Process started"
p.join()

注意:我只是在子进程中对stdin / stdout进行了硬编码处理。而且,既然您提到了python 2.7,就避免使用for line in stdin: