Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 33.9k
Closed
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-asynciotype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
Bug report
Bug description:
asyncio.TaskGroup attempts to avoid refcycles in raised exceptions by deleting self._errors but when I reviewed the code it doesn't actually achieve this:
see
cpython/Lib/asyncio/taskgroups.py
Lines 152 to 156 in 5e9e506
| try: | |
| me=BaseExceptionGroup('unhandled errors in a TaskGroup', self._errors) | |
| raisemefromNone | |
| finally: | |
| self._errors=None |
There's a refcycle in me is me.__traceback__.tb_next.tb_frame.f_locals["me"]
I wrote a few tests to route out all the refcycles in tracebacks
importasyncioimportgcimportunittestclassTestTaskGroup(unittest.IsolatedAsyncioTestCase): asyncdeftest_exception_refcycles_direct(self): """Test that TaskGroup doesn't keep a reference to the raised ExceptionGroup"""tg=asyncio.TaskGroup() exc=Noneclass_Done(Exception): passtry: asyncwithtg: raise_DoneexceptExceptionGroupase: exc=eself.assertIsNotNone(exc) self.assertListEqual(gc.get_referrers(exc), []) asyncdeftest_exception_refcycles_errors(self): """Test that TaskGroup deletes self._errors, and __aexit__ args"""tg=asyncio.TaskGroup() exc=Noneclass_Done(Exception): passtry: asyncwithtg: raise_Done except* _Doneasexcs: exc=excs.exceptions[0] self.assertIsInstance(exc, _Done) self.assertListEqual(gc.get_referrers(exc), []) asyncdeftest_exception_refcycles_parent_task(self): """Test that TaskGroup deletes self._parent_task"""tg=asyncio.TaskGroup() exc=Noneclass_Done(Exception): passasyncdefcoro_fn(): asyncwithtg: raise_Donetry: asyncwithasyncio.TaskGroup() astg2: tg2.create_task(coro_fn()) except* _Doneasexcs: exc=excs.exceptions[0].exceptions[0] self.assertIsInstance(exc, _Done) self.assertListEqual(gc.get_referrers(exc), []) asyncdeftest_exception_refcycles_propagate_cancellation_error(self): """Test that TaskGroup deletes propagate_cancellation_error"""tg=asyncio.TaskGroup() exc=Nonetry: asyncwithasyncio.timeout(-1): asyncwithtg: awaitasyncio.sleep(0) exceptTimeoutErrorase: exc=e.__cause__self.assertIsInstance(exc, asyncio.CancelledError) self.assertListEqual(gc.get_referrers(exc), []) asyncdeftest_exception_refcycles_base_error(self): """Test that TaskGroup deletes self._base_error"""classMyKeyboardInterrupt(KeyboardInterrupt): passtg=asyncio.TaskGroup() exc=Nonetry: asyncwithtg: raiseMyKeyboardInterruptexceptMyKeyboardInterruptase: exc=eself.assertIsNotNone(exc) self.assertListEqual(gc.get_referrers(exc), [])in writing all these tests I noticed refcycles in PyFuture:
cpython/Lib/asyncio/futures.py
Lines 197 to 198 in 58f7763
| exc=self._make_cancelled_error() | |
| raiseexc |
cpython/Lib/asyncio/futures.py
Lines 215 to 216 in 58f7763
| exc=self._make_cancelled_error() | |
| raiseexc |
classBaseFutureTests: deftest_future_cancelled_result_refcycles(self): f=self._new_future(loop=self.loop) f.cancel() exc=Nonetry: f.result() exceptasyncio.CancelledErrorase: exc=eself.assertIsNotNone(exc) self.assertListEqual(gc.get_referrers(exc), []) deftest_future_cancelled_exception_refcycles(self): f=self._new_future(loop=self.loop) f.cancel() exc=Nonetry: f.exception() exceptasyncio.CancelledErrorase: exc=eself.assertIsNotNone(exc) self.assertListEqual(gc.get_referrers(exc), [])CPython versions tested on:
3.12, 3.13
Operating systems tested on:
Linux
Linked PRs
- gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles #124959
- [3.13] gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles (GH-124959) #125463
- [3.12] gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles (#124959) #125466
- gh-124958: Revert "gh-125472: Revert "gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles ... #125486
Metadata
Metadata
Assignees
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-asynciotype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Projects
Status
Done