-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
gh-94215: Fix reference count issue in exception_unwind #94659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Misc/NEWS.d/next/Core and Builtins/2022-07-07-17-07-00.gh-issue-94215.cXltGH.rst
Show resolved
Hide resolved
🤖 New build scheduled with the buildbot fleet by @tiran for commit 990279b062ac4d61361ef7587e1977879606de52 🤖 If you want to schedule another build, you need to add the ":hammer: test-with-buildbots" label again. |
The fix seems to introduce a reference leak:
Leaking tests:
|
@encukou How did you figure out the leaking tests so quickly? I had to figure out that shell one-liner to run each test function separately. |
Umm, manually: deleting chunks of the test suite & only keeping the deletion if the leaks stayed at |
My approach takes longer, but is less manual work. |
There's also |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
At the least this seems to be an effective short-term solution. It may be valid for the long-term too. I've left some thoughts on the issue.
@tiran, applying this diff to your branch fixes the leaks for me: diff --git a/Python/ceval.c b/Python/ceval.c
index 083f881807..e23bfda725 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -5683,6 +5683,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
err = maybe_call_line_trace(tstate->c_tracefunc,
tstate->c_traceobj,
tstate, frame, instr_prev);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ frame->stacktop = -1;
if (err) {
/* trace function raised an exception */
next_instr++;
@@ -5690,9 +5692,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
}
/* Reload possibly changed frame fields */
next_instr = frame->prev_instr;
-
- stack_pointer = _PyFrame_GetStackPointer(frame);
- frame->stacktop = -1;
}
}
}
@@ -5795,11 +5794,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
/* Pop remaining stack entries. */
PyObject **stackbase = _PyFrame_Stackbase(frame);
- if (frame->stacktop != -1) {
- // frame_setlineno() may have popped off additional stacks in
- // frame_stack_pop(). Re-calculate stack pointer.
- stack_pointer = _PyFrame_GetStackPointer(frame);
- }
while (stack_pointer > stackbase) {
PyObject *o = POP();
Py_XDECREF(o); I'm not entirely sure why yet, but my understanding (gained over the last couple of hours) is that ...maybe? |
Zero-cost exception handling did not take ``frame_setlineno()`` into account. It can pop off stacks. This can lead to a crash. Exception unwinding now re-calculates the stack pointer. Co-authored-by: Irit Katriel <[email protected]>
990279b
to
cee2887
Compare
superseded by #94681 |
Zero-cost exception handling did not take
frame_setlineno()
intoaccount. It can pop off stacks. This can lead to a crash.
Exception unwinding now re-calculates the stack pointer.
Co-authored-by: Irit Katriel [email protected]