首页 文章

何时使用loop.add_signal_handler?

提问于
浏览
1

我注意到asyncio库有一个 loop.add_signal_handler(signum, callback, *args) 方法 .

到目前为止,我刚刚使用 signals 模块在主文件中捕获unix信号,我的异步代码如下:

signal.signal(signal.SIGHUP, callback)

async def main():
    ...

这是我的疏忽吗?

1 回答

  • 1

    add_signal_handler documentation是稀疏的,但是看the source,似乎与 signal.signal 相比的主要附加值是 add_signal_handler 将确保信号唤醒事件循环并允许循环调用信号处理程序以及其他排队的回调和runnable协同程序 .

    到目前为止,我刚刚使用信号模块在主文件中捕获unix信号[...]这是我的疏忽吗?

    这取决于信号处理程序正在做什么 . 打印消息或更新全局很好,但如果它以任何方式调用与asyncio相关的任何内容,则很可能是疏忽 . 信号可以在(几乎)任何时间传递,包括在执行asyncio回调,协程或甚至在asyncio自己的簿记期间 .

    例如, asyncio.Queue 的实现自由地假定对队列的访问是单线程且不可重入的 . 如果一个信号处理程序在同一队列中中断了 q.put_nowait() 的正在进行的调用,那么使用 q.put_nowait() 向队列添加内容将是灾难性的 . 与经典的线程竞争条件类似,分配到_unfinished_tasks中间的中断可能会导致它仅增加一次而不是两次 .

    Asyncio代码是designed用于协作多任务,其中函数可以暂停定义的点由 await 和相关关键字清楚地表示 . add_signal_handler 函数确保您的信号处理程序在这一点上被调用,并且您're free to implement it as you'd实现任何其他asyncio回调 .

相关问题