Reset monitoring reraise suppression at exception lifecycle boundaries

Clear the existing thread-local suppression flag when a handler receives an exception or an exception escapes a frame, independently of optional monitoring event masks.

Assisted-by: OpenAI Codex:model identifier unavailable
This commit is contained in:
dot committed 2026-10-13 11:06:28 +09:00
1 parent ec206b1125
commit 191fe58873
2 files changed
+11 -2

No files matched your search

+3
View File
@@ -4171,6 +4171,7 @@ impl ExecutingFrame<'_> {
Ok(None) => next_idx = lasti_cell.load(Relaxed),
Ok(Some(result)) => break Ok(Some(result)),
Err(exception) => {
monitoring::reset_reraise_pending();
// Fire PY_UNWIND: exception escapes this frame
let exception = if vm.state.monitoring_events.load()
& MonitoringEvent::PyUnwind.mask()
@@ -4454,6 +4455,7 @@ impl ExecutingFrame<'_> {
}
Ok(Some(result)) => Ok(result),
Err(exception) => {
monitoring::reset_reraise_pending();
// Fire PY_UNWIND: exception escapes the generator frame.
let exception =
if vm.state.monitoring_events.load() & MonitoringEvent::PyUnwind.mask() != 0 {
@@ -8922,6 +8924,7 @@ impl ExecutingFrame<'_> {
if let Some(entry) =
bytecode::find_exception_handler(&self.code.exceptiontable, offset)
{
monitoring::reset_reraise_pending();
// Fire EXCEPTION_HANDLED before setting up handler.
// If the callback raises, the handler is NOT set up and the
// new exception propagates instead.
+8 -2
View File
@@ -1083,6 +1083,12 @@ pub(crate) fn fire_raise(
)
}
/// End suppression when the exception reaches a handler or escapes a frame,
/// independently of whether either lifecycle event has a registered callback.
pub(crate) fn reset_reraise_pending() {
RERAISE_PENDING.with(|f| f.set(false));
}
/// Only fires if no RERAISE has been fired since the last EXCEPTION_HANDLED,
/// preventing duplicate events from chained cleanup handlers.
pub(crate) fn fire_reraise(
@@ -1114,7 +1120,7 @@ pub(crate) fn fire_exception_handled(
offset: u32,
exception: &PyObject,
) -> PyResult<()> {
RERAISE_PENDING.with(|f| f.set(false));
reset_reraise_pending();
fire(
vm,
MonitoringEvent::ExceptionHandled,
@@ -1130,7 +1136,7 @@ pub(crate) fn fire_py_unwind(
offset: u32,
exception: &PyObject,
) -> PyResult<()> {
RERAISE_PENDING.with(|f| f.set(false));
reset_reraise_pending();
fire(
vm,
MonitoringEvent::PyUnwind,