[英]Indirectly stopping a python asyncio event loop through SIGTERM has no effect
以下最小程序重現了該問題。
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()
如果運行程序並將SIGTERM發送到進程,則會調用第16行(停止事件循環)中的print語句,但程序不會終止,並且永遠不會調用第13行中的print語句(事件循環已停止)。 所以似乎事件循環永遠不會停止, self._event_loop.run_forever()
無限期地阻塞。
為什么是這樣?
注意:程序的修改版本,其中a.stop()
不是由信號處理程序調用,而是由具有延遲的單獨線程調用,按預期工作。 如何調用a.stop()
什么不同?
而不是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.