Skip to content

Commit 8e0de2a

Browse files
vxgmichelmiss-islington
authored andcommitted
bpo-35409: Ignore GeneratorExit in async_gen_athrow_throw (GH-14755)
Ignore `GeneratorExit` exceptions when throwing an exception into the `aclose` coroutine of an asynchronous generator. https://bugs.python.org/issue35409
1 parent f25875a commit 8e0de2a

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

Lib/test/test_asyncgen.py

+27
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,33 @@ async def run():
735735
self.loop.run_until_complete(run())
736736
self.assertEqual(DONE, 10)
737737

738+
def test_async_gen_asyncio_aclose_12(self):
739+
DONE = 0
740+
741+
async def target():
742+
await asyncio.sleep(0.01)
743+
1 / 0
744+
745+
async def foo():
746+
nonlocal DONE
747+
task = asyncio.create_task(target())
748+
try:
749+
yield 1
750+
finally:
751+
try:
752+
await task
753+
except ZeroDivisionError:
754+
DONE = 1
755+
756+
async def run():
757+
gen = foo()
758+
it = gen.__aiter__()
759+
await it.__anext__()
760+
await gen.aclose()
761+
762+
self.loop.run_until_complete(run())
763+
self.assertEqual(DONE, 1)
764+
738765
def test_async_gen_asyncio_asend_01(self):
739766
DONE = 0
740767

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Ignore GeneratorExit exceptions when throwing an exception into the aclose
2+
coroutine of an asynchronous generator.

Objects/genobject.c

+11
Original file line numberDiff line numberDiff line change
@@ -1932,6 +1932,17 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *args)
19321932
PyErr_SetString(PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
19331933
return NULL;
19341934
}
1935+
if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) ||
1936+
PyErr_ExceptionMatches(PyExc_GeneratorExit))
1937+
{
1938+
/* when aclose() is called we don't want to propagate
1939+
StopAsyncIteration or GeneratorExit; just raise
1940+
StopIteration, signalling that this 'aclose()' await
1941+
is done.
1942+
*/
1943+
PyErr_Clear();
1944+
PyErr_SetNone(PyExc_StopIteration);
1945+
}
19351946
return retval;
19361947
}
19371948
}

0 commit comments

Comments
 (0)