Issue
I noticed the asyncio library has a loop.add_signal_handler(signum, callback, *args)
method.
So far I have just been catching unix signals in the main file using the signals
module in with my asynchronous code like this:
signal.signal(signal.SIGHUP, callback)
async def main():
...
Is that an oversight on my part?
Solution
The add_signal_handler
documentation is sparse1, but looking at the source, it appears that the main added value compared to signal.signal
is that add_signal_handler
will ensure that the signal wakes up the event loop and allow the loop to invoke the signal handler along with other queued callbacks and runnable coroutines.
So far I have just been catching unix signals in the main file using the signals module [...] Is that an oversight on my part?
That depends on what the signal handler is doing. Printing a message or updating a global is fine, but if it is invoking anything in any way related to asyncio, it's most likely an oversight. A signal can be delivered at (almost) any time, including during execution of an asyncio callback, a coroutine, or even during asyncio's own bookkeeping.
For example, the implementation of asyncio.Queue
freely assumes that the access to the queue is single-threaded and non-reentrant. A signal handler adding something to a queue using q.put_nowait()
would be disastrous if it interrupted an on-going invocation of q.put_nowait()
on the same queue. Similar to typical race conditions experienced in multi-threaded code, an interruption in the middle of assignment to _unfinished_tasks
might well cause it to get incremented only once instead of twice (once for each put_nowait
).
Asyncio code is designed for cooperative multi-tasking, where the points where a function may suspend defined are clearly denoted by the await
and related keywords. The add_signal_handler
function ensures that your signal handler gets invoked at such a point, and that you're free to implement it as you'd implement any other asyncio callback.
1 When this answer was originally written, the
add_signal_handler
documentation was briefer than today and didn't cover the difference to signal.signal
at all. This question prompted it getting expanded in the meantime.
Answered By - user4815162342
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.