Python:在后台进程中忽略信号

时间:2014-02-25 01:01:49

标签: python multithreading signals

我正在创建一个定期调用外部命令的Python程序。外部命令需要一些 秒完成。我想减少外部命令终止的可能性 通过为SIGINT添加信号处理程序很糟糕。基本上,我希望SIGINT尝试等到命令 在终止Python程序之前执行。问题是外部的周长似乎是 获得SIGINT,导致它突然结束。我正在使用外部线程调用该命令,因为 根据{{​​3}},信号的Python文档提到只有主线程接收信号。 有人可以帮忙吗? 这是我的代码的存根。想象一下,外部程序是/ bin / sleep:

import sys
import time
import threading
import signal
def sleep():
  import subprocess
  global sleeping
  cmd = ['/bin/sleep', '10000']
  sleeping  = True
  p = subprocess.Popen(cmd)
  p.wait()
  sleeping = False

def sigint_handler(signum, frame):
  if sleeping:
     print 'busy, will terminate shortly'
     while(sleeping): time.sleep(0.5)
     sys.exit(0)
  else:
     print 'clean exit'
     sys.exit(0)

sleeping = False
signal.signal(signal.SIGINT, sigint_handler)
while(1):
  t1 = threading.Thread(target=sleep)
  t1.start()
  time.sleep(500)

预期的行为是在程序启动后按Ctrl + C N秒将导致 它等待(10000 - N)秒然后退出。发生的事情是程序立即终止。

谢谢!

1 个答案:

答案 0 :(得分:3)

问题在于执行新进程时信号处理程序的修改方式。来自POSIX:

A child created via fork(2) inherits a copy of its parent's signal dis‐
positions.  During an execve(2), the dispositions  of  handled  signals
are  reset to the default; the dispositions of ignored signals are left
unchanged.

所以你需要做的是:

  1. 忽略SIGINT信号
  2. 启动外部程序
  3. 根据需要设置SIGINT处理程序
  4. 这样,外部程序将忽略SIGINT。

    当然,当脚本不响应SIGINT时,这会留下(非常)小的时间窗口。但那是你必须忍受的东西。

    例如:

    sleeping = False
    while(1):
        t1 = threading.Thread(target=sleep)
        signal.signal(signal.SIGINT, signal.SIG_IGN)
        t1.start()
        signal.signal(signal.SIGINT, sigint_handler)
        time.sleep(500)