我有一个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()
答案 0 :(得分: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()
此脚本的示例运行如下:
$ ./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
子进程没有回溯,流程显示子进程以正常方式退出。这是因为SIGTERM被子进程信号处理程序捕获,该处理程序抛出了一个可以在进程内处理的普通Python异常。