How can coroutines be used in signal handlers?

1,649 views
Skip to first unread message

jinn...@openmailbox.org

unread,
Apr 27, 2014, 6:20:00 AM4/27/14
to python...@googlegroups.com
I am developing an application that uses asyncio from python3.4 for networking. When this application shuts down cleanly, a node needs to "disconnect" from the hub.
This disconnect is an active process that requires a network connection so the loop needs to wait for this to complete before shutting down.

My issue is that using a coroutine as a signal handler will result in the application not shutting down. Please consider the following example:
   
    import asyncio
    import functools
    import os
    import signal
   
    @asyncio.coroutine
    def ask_exit(signame):
        print("got signal %s: exit" % signame)
        yield from asyncio.sleep(10.0)
        loop.stop()
   
    loop = asyncio.get_event_loop()
    for signame in ('SIGINT', 'SIGTERM'):
        loop.add_signal_handler(getattr(signal, signame),
                                            functools.partial(ask_exit, signame))
   
    print("Event loop running forever, press CTRL+c to interrupt.")
    print("pid %s: send SIGINT or SIGTERM to exit." % os.getpid())
    loop.run_forever()


If you run this example and then press Ctrl+C, nothing will happen.
The question is, how do I make this behavior happen with siganls and coroutines?


PS: If you want to earn points, I have also asked this on stackoverflow:
https://stackoverflow.com/questions/23313720/asyncio-how-can-coroutines-be-used-in-signal-handlers

Luca Sbardella

unread,
Apr 27, 2014, 7:01:31 AM4/27/14
to jinn...@openmailbox.org, python-tulip
Hi,

On 27 April 2014 11:20, <jinn...@openmailbox.org> wrote:
I am developing an application that uses asyncio from python3.4 for networking. When this application shuts down cleanly, a node needs to "disconnect" from the hub.
This disconnect is an active process that requires a network connection so the loop needs to wait for this to complete before shutting down.

My issue is that using a coroutine as a signal handler will result in the application not shutting down. Please consider the following example:
   
    import asyncio
    import functools
    import os
    import signal
   
    @asyncio.coroutine
    def ask_exit(signame):
        print("got signal %s: exit" % signame)
        yield from asyncio.sleep(10.0)
        loop.stop()
   
    loop = asyncio.get_event_loop()
    for signame in ('SIGINT', 'SIGTERM'):
        loop.add_signal_handler(getattr(signal, signame),
                                            functools.partial(ask_exit, signame))
   
    print("Event loop running forever, press CTRL+c to interrupt.")
    print("pid %s: send SIGINT or SIGTERM to exit." % os.getpid())
    loop.run_forever()


If you run this example and then press Ctrl+C, nothing will happen.
The question is, how do I make this behavior happen with siganls and coroutines?

The signal handler cannot return a coroutine.
If you replace:

loop.add_signal_handler(getattr(signal, signame),
                                            functools.partial(ask_exit, signame))

with

loop.add_signal_handler(getattr(signal, signame), lambda: asyncio.async(ask_exit(signame)))


your example will work fine.
The async function runs your coroutine in the event loop.
 

PS: If you want to earn points, I have also asked this on stackoverflow:
https://stackoverflow.com/questions/23313720/asyncio-how-can-coroutines-be-used-in-signal-handlers

jinn...@openmailbox.org

unread,
Apr 27, 2014, 7:16:16 AM4/27/14
to python...@googlegroups.com, jinn...@openmailbox.org
Hi Luca,


Am Sonntag, 27. April 2014 11:01:31 UTC schrieb Luca Sbardella:
The signal handler cannot return a coroutine.
If you replace:

loop.add_signal_handler(getattr(signal, signame),
                                            functools.partial(ask_exit, signame))

with

loop.add_signal_handler(getattr(signal, signame), lambda: asyncio.async(ask_exit(signame)))


your example will work fine.
The async function runs your coroutine in the event loop.

This does indeed work. Thank you very much.

Victor Stinner

unread,
Apr 27, 2014, 9:13:11 AM4/27/14
to jinn...@openmailbox.org, python...@googlegroups.com
Your question is a frequent question. We should enhance the documentation to explain how to use coroutines in protocols, signal handlers and all other places using callbacks, maybe with a few simple examples.

Victor
Reply all
Reply to author
Forward
0 new messages