Skip to content

gen: Release frames after caught exceptions - #3694

Open
Sanjays2402 wants to merge 1 commit into
tornadoweb:masterfrom
Sanjays2402:fix/gen-caught-exception-cycle
Open

gen: Release frames after caught exceptions#3694
Sanjays2402 wants to merge 1 commit into
tornadoweb:masterfrom
Sanjays2402:fix/gen-caught-exception-cycle

Conversation

@Sanjays2402

Copy link
Copy Markdown

Fixes #3346.

When a @gen.coroutine catches an exception from a yielded Future, gen.throw() leaves the receiving generator frame on the exception traceback. The Future retains that exception, closing a cycle through the Runner callback stack and keeping frame locals alive until cyclic GC.

Restore the pre-throw traceback once the coroutine handles the exception, whether it returns or yields again. The regression test verifies CPython releases those locals immediately in both paths.

Tests: gen_test passes on Python 3.10, 3.13, and 3.14; flake8, black, and mypy pass. The full suite's sole failure (StaticDefaultFilenameRootTest.test_no_open_redirect on macOS) reproduces unchanged on master.

When a coroutine catches an exception from a yielded Future, gen.throw()
adds the receiving generator frame to the exception traceback. The Future
retains that exception, forming a cycle that keeps frame locals alive until
cyclic garbage collection runs.

Restore the pre-throw traceback after the generator handles the exception,
covering both return and yield paths. Add a refcounting regression test.

Fixes tornadoweb#3346
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Possible leak when exception is raised in inner coroutine

1 participant