@@ -608,6 +608,39 @@ async def runner():
608608 get_error_types (cm .exception ), {MyBaseExc , ZeroDivisionError }
609609 )
610610
611+ async def test_taskgroup_20b (self ):
612+ # Same setup as test_taskgroup_20 (a KeyboardInterrupt from the
613+ # "async with" body itself, alongside a sibling task's exception):
614+ # raising self._base_error out of _aexit() discards self._errors
615+ # silently. The sibling's exception can't be raised alongside
616+ # the KeyboardInterrupt (only one exception can propagate), but
617+ # it must be reported via the loop's exception handler instead
618+ # of being discarded silently. See gh-135736.
619+ async def crash_soon ():
620+ await asyncio .sleep (0.1 )
621+ 1 / 0
622+
623+ async def nested ():
624+ try :
625+ await asyncio .sleep (10 )
626+ finally :
627+ raise KeyboardInterrupt
628+
629+ async def runner ():
630+ async with taskgroups .TaskGroup () as g :
631+ g .create_task (crash_soon ())
632+ await nested ()
633+
634+ contexts = []
635+ loop = asyncio .get_running_loop ()
636+ loop .set_exception_handler (lambda loop , context : contexts .append (context ))
637+
638+ with self .assertRaises (KeyboardInterrupt ):
639+ await runner ()
640+
641+ self .assertEqual (len (contexts ), 1 )
642+ self .assertIsInstance (contexts [0 ]['exception' ], ZeroDivisionError )
643+
611644 async def _test_taskgroup_21 (self ):
612645 # This test doesn't work as asyncio, currently, doesn't
613646 # correctly propagate KeyboardInterrupt (or SystemExit) --
0 commit comments