Skip to content

Asyncio does not handle nested KeyboardInterrupt correctly #146194

Description

@user202729

Bug report

Bug description:

Consider this code

importsysimportloggingimportasyncioimportsignalfromtimeimport*logger=logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
asyncdeff():
if1:
main_task=asyncio.current_task()
defon_sigint() ->None:
logger.error("Received SIGINT")
main_task.cancel(KeyboardInterrupt)
asyncio.get_running_loop().add_signal_handler(signal.SIGINT, on_sigint)
try:
whileTrue:
awaitasyncio.sleep(0.1)
print("*")
exceptasyncio.CancelledErrorase:
print(e)
try:
whileTrue:
awaitasyncio.sleep(0.1)
print("#")
exceptasyncio.CancelledError:
try:
whileTrue:
awaitasyncio.sleep(0.1)
print("!")
exceptasyncio.CancelledError:
whileTrue:
awaitasyncio.sleep(0.1)
print("@")
asyncio.run(f())

Intention: each time I press Ctrl-C, it repeatedly print *, #, !, @ respectively.

As is, it does do that correctly.

However, if I don't manually add the SIGINT signal handler, it will print *, {first Ctrl-C} #, {second Ctrl-C} !, {third Ctrl-C} then forcefully stop.

I don't think this behavior is desirable. Or at least it probably shouldn't log a scary error Task was destroyed but it is pending!?

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytopic-asynciotype-bugAn unexpected behavior, bug, or error

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions