python-trio / trio-asyncio

a re-implementation of the asyncio mainloop on top of Trio

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

asyncio functions raising KeyboardInterrupt/SystemExit can produce a deadlock

oremanj opened this issue · comments

asyncio contains a number of special-cases where KeyboardInterrupt and SystemExit are handled differently than other exceptions: they are allowed to propagate out of the event loop, rather than (or in some cases in addition to) being set as the result of a future or passed to the default_exception_handler. Presumably this was done as an ugly-but-practical solution to the endless stream of "asyncio hangs when you press Ctrl-C!" bugs.

trio_asyncio does not deal well with the event loop raising an exception without resolving all its futures. In some other part of the program, there is a call to run_aio_future which is uninterruptibly waiting to see what that future resolves to. If the event loop exits, the future will never be resolved. Boom, deadlock.

This isn't much of a problem with actual keyboard interrupts, because we can (mostly) route those using restrict_keyboard_interrupt_to_checkpoints so they aren't raised within asyncio-flavored code. But it definitely breaks code that uses KeyboardInterrupt as a normal signaling exception. I ran into this when using prompt_toolkit; by default it produces a KeyboardInterrupt exception when it reads Ctrl+C from the terminal (the terminal is in raw mode so this doesn't produce a SIGINT). Under trio_asyncio such a Ctrl+C can produce a deadlock instead.