[英]Indirectly stopping a python asyncio event loop through SIGTERM has no effect
The following minimal program reproduces the problem. 以下最小程序重现了该问题。
import asyncio
import signal
class A:
def __init__(self):
self._event_loop = asyncio.new_event_loop()
def run(self):
print('starting event loop')
self._event_loop.run_forever()
print('event loop has stopped')
def stop(self):
print('stopping event loop')
self._event_loop.stop()
if __name__ == '__main__':
a = A()
def handle_term(*args):
a.stop()
signal.signal(signal.SIGTERM, handle_term)
a.run()
If you run the program and send a SIGTERM to the process, the print statement in line 16 (stopping event loop) is called but the programm does not terminate and the print statement in line 13 (event loop has stopped) is never called. 如果运行程序并将SIGTERM发送到进程,则会调用第16行(停止事件循环)中的print语句,但程序不会终止,并且永远不会调用第13行中的print语句(事件循环已停止)。 So it seems that the event loop is never stopped and
self._event_loop.run_forever()
blocks indefinitely. 所以似乎事件循环永远不会停止,
self._event_loop.run_forever()
无限期地阻塞。
Why is this? 为什么是这样?
Note: A modified version of the program, where a.stop()
is not called by a signal handler but by a seperate thread with a delay, works as expected. 注意:程序的修改版本,其中
a.stop()
不是由信号处理程序调用,而是由具有延迟的单独线程调用,按预期工作。 How can it make a difference how a.stop()
is called? 如何调用
a.stop()
什么不同?
Instead of signal.signal()
use loop.add_signal_handler()
: 而不是
signal.signal()
使用loop.add_signal_handler()
:
import asyncio
import signal
import os
class A:
def __init__(self):
self.loop = asyncio.new_event_loop()
self.loop.add_signal_handler(signal.SIGTERM, self.stop)
def stop(self):
print('stopping')
self.loop.stop()
def run(self, close=True):
print('starting loop')
try:
self.loop.run_forever()
print('loop stopped')
finally:
if close:
self.loop.close()
if __name__ == '__main__':
print("to stop run:\nkill -TERM {}".format(os.getpid()))
a = A()
a.run()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.