Bug report
Bug description:
Eager tasks created from an except block inherits the creator's exception state, a bare raise re-raises it, and any other exception gets it as __context__.
Repro:
import asyncio
async def bare():
raise
async def explicit():
raise ValueError("child's own")
async def main(coro):
try:
raise ConnectionError("primary failed")
except ConnectionError:
t = asyncio.create_task(coro)
try:
await t
except BaseException as e:
print(f" {type(e).__name__}: {e} | __context__: {e.__context__!r}")
for eager in (False, True):
print("eager_task_factory:", eager)
for coro_fn in (bare, explicit):
loop = asyncio.new_event_loop()
if eager:
loop.set_task_factory(asyncio.eager_task_factory)
try:
loop.run_until_complete(main(coro_fn()))
finally:
loop.close()
expected:
eager_task_factory: False
RuntimeError: No active exception to reraise | __context__: None
ValueError: child's own | __context__: None
eager_task_factory: True
RuntimeError: No active exception to reraise | __context__: None
ValueError: child's own | __context__: None
actually:
eager_task_factory: False
RuntimeError: No active exception to reraise | __context__: None
ValueError: child's own | __context__: None
eager_task_factory: True
ConnectionError: primary failed | __context__: None
ValueError: child's own | __context__: ConnectionError('primary failed')
proposed fix - run the eager first step under an empty exception state in task_eager_start
_PyErr_StackItem exc_state = { .exc_value = NULL, .previous_item = NULL };
_PyErr_StackItem *prev_exc_info = ts->base.exc_info;
ts->base.exc_info = &exc_state;
Py_BEGIN_CRITICAL_SECTION(task);
stepres = task_step_impl(state, task, NULL);
Py_END_CRITICAL_SECTION();
ts->base.exc_info = prev_exc_info;
This error also affects python implementation of task, but i think this needs a discussion in a separate issue
Have a fix ready
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Linked PRs
Bug report
Bug description:
Eager tasks created from an except block inherits the creator's exception state, a bare raise re-raises it, and any other exception gets it as
__context__.Repro:
expected:
actually:
proposed fix - run the eager first step under an empty exception state in
task_eager_startThis error also affects python implementation of task, but i think this needs a discussion in a separate issue
Have a fix ready
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS
Linked PRs