diff --git a/Python/ceval.c b/Python/ceval.c index 46bf644106ac39..b1cdd4716d1c9e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1407,6 +1407,10 @@ stop_tracing_and_jit(PyThreadState *tstate, _PyInterpreterFrame *frame) else { // Likewise, we hold a strong reference to the executor containing this exit, so the exit is guaranteed // to be valid to access. + if (!exit->executor->vm_data.linked || !exit->executor->vm_data.valid) { + // gh-141786 Parent executor is either unlinked or invalid - cannot optimize. + err = -1; + } if (err <= 0) { exit->temperature = restart_backoff_counter(exit->temperature); } diff --git a/Python/optimizer.c b/Python/optimizer.c index 9db894f0bf054a..81d0ec0b0962fc 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -140,6 +140,11 @@ _PyOptimizer_Optimize( } assert(!interp->compiling); assert(_tstate->jit_tracer_state.initial_state.stack_depth >= 0); + _PyExitData *exit = _tstate->jit_tracer_state.initial_state.exit; + if (exit != NULL && (!exit->executor->vm_data.linked || !exit->executor->vm_data.valid)) { + // gh-141786 Parent executor is either unlinked or invalid - cannot optimize. + return 0; + } #ifndef Py_GIL_DISABLED assert(_tstate->jit_tracer_state.initial_state.func != NULL); interp->compiling = true; @@ -185,7 +190,6 @@ _PyOptimizer_Optimize( else { executor->vm_data.code = NULL; } - _PyExitData *exit = _tstate->jit_tracer_state.initial_state.exit; if (exit != NULL) { exit->executor = executor; }