在等待信号量的同时接收SIGTERM后,python进程如何正常退出?

Dip*_*jee 10 python python-multiprocessing

我有一个Python进程,使用多处理模块生成其他5个Python进程.让我们调用父进程P0和其他P1-P5.要求是,如果我们将SIGTERM发送到P0,它应该首先关闭P1到P5然后退出自己.

问题是P1和P5正在等待信号量.因此,当我将SIGTERM发送到这些进程时,它们会调用信号处理程序并退出.但由于他们正在等待信号量,他们会抛出异常.有没有办法在退出之前捕获该异常,以便P0到P5可以正常退出?

追溯:

Traceback (most recent call last):
  File "/usr/lib64/python2.7/multiprocessing/process.py", line 258, in _bootstrap
Traceback (most recent call last):
Process Process-2:
  File "/usr/lib64/python2.7/multiprocessing/process.py", line 258, in _bootstrap
Traceback (most recent call last):
self.run()
File "/usr/lib64/python2.7/multiprocessing/process.py", line 114, in run
self._target(*self._args, **self._kwargs)
Process Process-5:
Traceback (most recent call last):
File "/usr/lib64/python2.7/multiprocessing/process.py", line 258, in _bootstrap
  self.run()
File "/usr/lib64/python2.7/multiprocessing/process.py", line 114, in run
  self._target(*self._args, **self._kwargs)
File "/opt/fireeye/scripts/mip/StaticAnalysisRunner.py", line 45, in run
  qsem.acquire()
Run Code Online (Sandbox Code Playgroud)

Aus*_*ips 13

您可以安装一个抛出异常的信号处理程序,然后在子进程中捕获该异常以正常处理退出.

下面是一个脚本示例,它在子进程中的信号量中等待,并在发送时正常终止SIGTERM.

#!/usr/bin/env python

import signal
import time
import multiprocessing

class GracefulExit(Exception):
    pass


def signal_handler(signum, frame):
    raise GracefulExit()


def subprocess_function():
    try:
        sem = multiprocessing.Semaphore()
        print "Acquiring semaphore"
        sem.acquire()
        print "Semaphore acquired"

        print "Blocking on semaphore - waiting for SIGTERM"
        sem.acquire()
    except GracefulExit:
        print "Subprocess exiting gracefully"


if __name__ == "__main__":

    # Use signal handler to throw exception which can be caught to allow
    # graceful exit.
    signal.signal(signal.SIGTERM, signal_handler)

    # Start a subprocess and wait for it to terminate.
    p = multiprocessing.Process(target=subprocess_function)
    p.start()

    print "Subprocess pid: %d" % p.pid

    p.join()
Run Code Online (Sandbox Code Playgroud)

此脚本的示例运行如下:

$ ./test.py 
Subprocess pid: 7546
Acquiring semaphore
Semaphore acquired
Blocking on semaphore - waiting for SIGTERM
----> Use another shell to kill -TERM 7546
Subprocess exiting gracefully
Run Code Online (Sandbox Code Playgroud)

子流程没有回溯,流程显示子流程以优雅的方式退出.这是因为SIGTERM被子进程信号处理程序捕获,该处理程序抛出了一个可以在进程内处理的普通Python异常.