aknuds1
aknuds1

Reputation: 68117

Why can't I catch SIGINT when asyncio event loop is running?

Using Python 3.4.1 on Windows, I've found that while executing an asyncio event loop, my program can't be interrupted (i.e. by pressing Ctrl+C in the terminal). More to the point, the SIGINT signal is ignored. Conversely, I've determined that SIGINT is handled when not in an event loop.

Why is it that SIGINT is ignored when executing an asyncio event loop?

The below program should demonstrate the problem - run it in the terminal and try to stop it by pressing Ctrl+C, it should keep running:

import asyncio
import signal


# Never gets called after entering event loop
def handler(*args):
    print('Signaled')


signal.signal(signal.SIGINT, handler)

print('Event loop starting')
loop = asyncio.SelectorEventLoop()
asyncio.set_event_loop(loop)
loop.run_forever()
print('Event loop ended')

See discussion on official (Tulip) mailing list.

Upvotes: 17

Views: 6123

Answers (3)

Kjell Schubert
Kjell Schubert

Reputation: 147

I've found that while executing an asyncio event loop, my program can't be interrupted (i.e. by pressing Ctrl+C in the terminal)

To clarify: ctrl-C may not work, but ctrl-break works just fine.

Upvotes: 6

aknuds1
aknuds1

Reputation: 68117

I've found a workaround, which is to schedule a periodic callback. While this running, SIGINT is apparently processed:

import asyncio


def wakeup():
    # Call again
    loop.call_later(0.1, wakeup)


print('Event loop starting')
loop = asyncio.SelectorEventLoop()
# Register periodic callback
loop.call_later(0.1, wakeup)
asyncio.set_event_loop(loop)
loop.run_forever()
print('Event loop ended')

Not sure why this is necessary, but it indicates that signals are blocked while the event loop waits for events ("polls").

The matter has been discussed on the official (Tulip) mailing list, my workaround is apparently the way to go as of now.

Update

A fix has supposedly made its way into Python 3.5, so hopefully my workaround will be made obsolete by that Python version.

Upvotes: 15

Ivo
Ivo

Reputation: 5420

Normally, you would add a callback for these with loop.add_signal_handler() but apparently unfortunately this functionality is not supported with the inbuilt Windows event loops :/

A periodic check could be used, yes. Otherwise the loop runs outside of signal module's ability to trap signals.

Upvotes: 3

Related Questions