Commit 7d99f9e
Fix debug-mode segfault when the asyncgen finalizer hook runs during frame teardown
The asyncgen finalizer hook can be invoked by a dealloc while CPython is
mid-way through clearing the current interpreter frame
(_PyEval_FrameClearAndPop -> PyObject_CallFinalizerFromDealloc ->
_asyncgen_finalizer_hook). In debug mode the hook's call_soon_threadsafe
creates a Handle whose source-traceback capture calls sys._getframe(),
which dereferences the half-cleared frame (garbage frame_obj) and
segfaults the interpreter.
Observed in production on CPython 3.13.14 under streaming HTTP load
(starlette request.stream() async generators being GC'd under
cancellation churn): worker SIGSEGV within seconds of enabling
loop.set_debug(True). Reproduces on 3.13 and 3.14, x86_64 and aarch64.
Fix: skip source-traceback capture (per-thread flag) for handles created
from the finalizer hook -- the traceback of a GC point is meaningless for
debugging anyway -- and make extract_stack() tolerate AttributeError/
ValueError/TypeError from walk_stack, which py3.14 can raise when
non-frame objects (e.g. _asyncio.TaskStepMethWrapper) appear in the
stack (#715).1 parent e8efea4 commit 7d99f9e
3 files changed
Lines changed: 27 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
416 | 416 | | |
417 | 417 | | |
418 | 418 | | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
419 | 428 | | |
420 | 429 | | |
421 | 430 | | |
422 | 431 | | |
| 432 | + | |
| 433 | + | |
423 | 434 | | |
424 | 435 | | |
425 | 436 | | |
| |||
433 | 444 | | |
434 | 445 | | |
435 | 446 | | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
436 | 452 | | |
437 | 453 | | |
438 | 454 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
139 | 139 | | |
140 | 140 | | |
141 | 141 | | |
| 142 | + | |
142 | 143 | | |
143 | 144 | | |
144 | 145 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3195 | 3195 | | |
3196 | 3196 | | |
3197 | 3197 | | |
3198 | | - | |
| 3198 | + | |
| 3199 | + | |
| 3200 | + | |
| 3201 | + | |
| 3202 | + | |
| 3203 | + | |
| 3204 | + | |
| 3205 | + | |
| 3206 | + | |
| 3207 | + | |
3199 | 3208 | | |
3200 | 3209 | | |
3201 | 3210 | | |
| |||
0 commit comments