gh-137400: Fix a crash when disabling profiling across all threads (gh-137471)
The `PyEval_SetProfileAllThreads` function and other related functions had a race condition on `tstate->c_profilefunc` that could lead to a crash when disable profiling or tracing on all threads while another thread is starting to profile or trace a a call. There are still potential crashes when threads exit concurrently with profiling or tracing be enabled/disabled across all threads.
This commit is contained in:
@@ -477,13 +477,16 @@ setup_profile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg, PyObject
|
||||
}
|
||||
}
|
||||
|
||||
_PyEval_StopTheWorld(tstate->interp);
|
||||
int delta = (func != NULL) - (tstate->c_profilefunc != NULL);
|
||||
tstate->c_profilefunc = func;
|
||||
*old_profileobj = tstate->c_profileobj;
|
||||
tstate->c_profileobj = Py_XNewRef(arg);
|
||||
tstate->interp->sys_profiling_threads += delta;
|
||||
assert(tstate->interp->sys_profiling_threads >= 0);
|
||||
return tstate->interp->sys_profiling_threads;
|
||||
Py_ssize_t profiling_threads = tstate->interp->sys_profiling_threads;
|
||||
_PyEval_StartTheWorld(tstate->interp);
|
||||
return profiling_threads;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -574,13 +577,16 @@ setup_tracing(PyThreadState *tstate, Py_tracefunc func, PyObject *arg, PyObject
|
||||
}
|
||||
}
|
||||
|
||||
_PyEval_StopTheWorld(tstate->interp);
|
||||
int delta = (func != NULL) - (tstate->c_tracefunc != NULL);
|
||||
tstate->c_tracefunc = func;
|
||||
*old_traceobj = tstate->c_traceobj;
|
||||
tstate->c_traceobj = Py_XNewRef(arg);
|
||||
tstate->interp->sys_tracing_threads += delta;
|
||||
assert(tstate->interp->sys_tracing_threads >= 0);
|
||||
return tstate->interp->sys_tracing_threads;
|
||||
Py_ssize_t tracing_threads = tstate->interp->sys_tracing_threads;
|
||||
_PyEval_StartTheWorld(tstate->interp);
|
||||
return tracing_threads;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
Reference in New Issue
Block a user