Skip to content

Commit 5d5d92b

Browse files
miss-islingtoniaalmkumaraditya303
authored
[3.14] gh-105836: Fix asyncio.run_coroutine_threadsafe leaving underlying cancelled asyncio task running (GH-141696) (#142358)
gh-105836: Fix `asyncio.run_coroutine_threadsafe` leaving underlying cancelled asyncio task running (GH-141696) (cherry picked from commit 14715e3) Co-authored-by: Kaisheng Xu <[email protected]> Co-authored-by: Kumar Aditya <[email protected]>
1 parent 43f696d commit 5d5d92b

File tree

4 files changed

+29
-2
lines changed

4 files changed

+29
-2
lines changed

Lib/asyncio/futures.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ def _set_state(future, other):
392392

393393
def _call_check_cancel(destination):
394394
if destination.cancelled():
395-
if source_loop is None or source_loop is dest_loop:
395+
if source_loop is None or source_loop is events._get_running_loop():
396396
source.cancel()
397397
else:
398398
source_loop.call_soon_threadsafe(source.cancel)
@@ -401,7 +401,7 @@ def _call_set_state(source):
401401
if (destination.cancelled() and
402402
dest_loop is not None and dest_loop.is_closed()):
403403
return
404-
if dest_loop is None or dest_loop is source_loop:
404+
if dest_loop is None or dest_loop is events._get_running_loop():
405405
_set_state(destination, source)
406406
else:
407407
if dest_loop.is_closed():

Lib/test/test_asyncio/test_tasks.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3680,6 +3680,30 @@ def task_factory(loop, coro):
36803680
(loop, context), kwargs = callback.call_args
36813681
self.assertEqual(context['exception'], exc_context.exception)
36823682

3683+
def test_run_coroutine_threadsafe_and_cancel(self):
3684+
task = None
3685+
thread_future = None
3686+
# Use a custom task factory to capture the created Task
3687+
def task_factory(loop, coro):
3688+
nonlocal task
3689+
task = asyncio.Task(coro, loop=loop)
3690+
return task
3691+
3692+
self.addCleanup(self.loop.set_task_factory,
3693+
self.loop.get_task_factory())
3694+
3695+
async def target():
3696+
nonlocal thread_future
3697+
self.loop.set_task_factory(task_factory)
3698+
thread_future = asyncio.run_coroutine_threadsafe(asyncio.sleep(10), self.loop)
3699+
await asyncio.sleep(0)
3700+
3701+
thread_future.cancel()
3702+
3703+
self.loop.run_until_complete(target())
3704+
self.assertTrue(task.cancelled())
3705+
self.assertTrue(thread_future.cancelled())
3706+
36833707

36843708
class SleepTests(test_utils.TestCase):
36853709
def setUp(self):

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2103,6 +2103,7 @@ Xiang Zhang
21032103
Robert Xiao
21042104
Florent Xicluna
21052105
Yanbo, Xie
2106+
Kaisheng Xu
21062107
Xinhang Xu
21072108
Arnon Yaari
21082109
Alakshendra Yadav
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :meth:`asyncio.run_coroutine_threadsafe` leaving underlying cancelled
2+
asyncio task running.

0 commit comments

Comments
 (0)