mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
bpo-39622: Interrupt the main asyncio task on Ctrl+C (GH-32105)
Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
This commit is contained in:
parent
04acfa94bb
commit
f08a191882
4 changed files with 122 additions and 2 deletions
|
@ -1,7 +1,9 @@
|
|||
import _thread
|
||||
import asyncio
|
||||
import contextvars
|
||||
import gc
|
||||
import re
|
||||
import threading
|
||||
import unittest
|
||||
|
||||
from unittest import mock
|
||||
|
@ -12,6 +14,10 @@ def tearDownModule():
|
|||
asyncio.set_event_loop_policy(None)
|
||||
|
||||
|
||||
def interrupt_self():
|
||||
_thread.interrupt_main()
|
||||
|
||||
|
||||
class TestPolicy(asyncio.AbstractEventLoopPolicy):
|
||||
|
||||
def __init__(self, loop_factory):
|
||||
|
@ -298,7 +304,7 @@ class RunnerTests(BaseTest):
|
|||
|
||||
self.assertEqual(2, runner.run(get_context()).get(cvar))
|
||||
|
||||
def test_recursine_run(self):
|
||||
def test_recursive_run(self):
|
||||
async def g():
|
||||
pass
|
||||
|
||||
|
@ -318,6 +324,57 @@ class RunnerTests(BaseTest):
|
|||
):
|
||||
runner.run(f())
|
||||
|
||||
def test_interrupt_call_soon(self):
|
||||
# The only case when task is not suspended by waiting a future
|
||||
# or another task
|
||||
assert threading.current_thread() is threading.main_thread()
|
||||
|
||||
async def coro():
|
||||
with self.assertRaises(asyncio.CancelledError):
|
||||
while True:
|
||||
await asyncio.sleep(0)
|
||||
raise asyncio.CancelledError()
|
||||
|
||||
with asyncio.Runner() as runner:
|
||||
runner.get_loop().call_later(0.1, interrupt_self)
|
||||
with self.assertRaises(KeyboardInterrupt):
|
||||
runner.run(coro())
|
||||
|
||||
def test_interrupt_wait(self):
|
||||
# interrupting when waiting a future cancels both future and main task
|
||||
assert threading.current_thread() is threading.main_thread()
|
||||
|
||||
async def coro(fut):
|
||||
with self.assertRaises(asyncio.CancelledError):
|
||||
await fut
|
||||
raise asyncio.CancelledError()
|
||||
|
||||
with asyncio.Runner() as runner:
|
||||
fut = runner.get_loop().create_future()
|
||||
runner.get_loop().call_later(0.1, interrupt_self)
|
||||
|
||||
with self.assertRaises(KeyboardInterrupt):
|
||||
runner.run(coro(fut))
|
||||
|
||||
self.assertTrue(fut.cancelled())
|
||||
|
||||
def test_interrupt_cancelled_task(self):
|
||||
# interrupting cancelled main task doesn't raise KeyboardInterrupt
|
||||
assert threading.current_thread() is threading.main_thread()
|
||||
|
||||
async def subtask(task):
|
||||
await asyncio.sleep(0)
|
||||
task.cancel()
|
||||
interrupt_self()
|
||||
|
||||
async def coro():
|
||||
asyncio.create_task(subtask(asyncio.current_task()))
|
||||
await asyncio.sleep(10)
|
||||
|
||||
with asyncio.Runner() as runner:
|
||||
with self.assertRaises(asyncio.CancelledError):
|
||||
runner.run(coro())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue