Skip to content

Commit 167dab3

Browse files
committed
Fix CI: repair critical-section scoping in PyException_SetContext (gh-69968)
Py_END_CRITICAL_SECTION() emits a closing brace, so calling it inside the nested if/while early-return path closed the wrong block and left 'base_self' undeclared after the loop. Restructure to a single exit: record the cycle with a flag, then release the lock before Py_DECREF. Also add the missing news entry. Co-authored-by: Muse Code (Meta Muse Spark)
1 parent 5d32953 commit 167dab3

2 files changed

Lines changed: 18 additions & 5 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Setting :attr:`~BaseException.__context__` to the exception itself now has no
2+
effect, and setting it to a chain containing the exception moves the
3+
exception to the start of the chain, preventing cycles.

‎Objects/exceptions.c‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,8 @@ PyException_SetContext(PyObject *self, PyObject *context)
554554
assert(PyExceptionInstance_Check(self));
555555
assert(context == NULL || PyExceptionInstance_Check(context));
556556

557+
int self_in_chain = 0;
558+
557559
Py_BEGIN_CRITICAL_SECTION(self);
558560
PyBaseExceptionObject *base_self = PyBaseExceptionObject_CAST(self);
559561

@@ -568,18 +570,26 @@ PyException_SetContext(PyObject *self, PyObject *context)
568570
base_self->context;
569571
base_self->context = context;
570572
}
571-
assert(Py_REFCNT(self) > 1);
572-
Py_END_CRITICAL_SECTION();
573-
Py_DECREF(self);
574-
return;
573+
self_in_chain = 1;
574+
break;
575575
}
576576
assert(PyExceptionInstance_Check(exc));
577577
prev_exc = exc;
578578
exc = PyBaseExceptionObject_CAST(exc)->context;
579579
}
580580

581-
Py_XSETREF(base_self->context, context);
581+
if (self_in_chain) {
582+
/* Self was already in the chain; drop the lost link reference. */
583+
assert(Py_REFCNT(self) > 1);
584+
}
585+
else {
586+
Py_XSETREF(base_self->context, context);
587+
}
582588
Py_END_CRITICAL_SECTION();
589+
590+
if (self_in_chain) {
591+
Py_DECREF(self);
592+
}
583593
}
584594

585595
PyObject *

0 commit comments

Comments
 (0)