self.set = not self.set
+@threading_helper.requires_working_threading()
+class SetProfileAllMultiThreaded(TestCase):
+ def test_profile_all_threads(self):
+ done = threading.Event()
+
+ def func():
+ pass
+
+ def bg_thread():
+ while not done.is_set():
+ func()
+ func()
+ func()
+ func()
+ func()
+
+ def my_profile(frame, event, arg):
+ return None
+
+ bg_threads = []
+ for i in range(10):
+ t = threading.Thread(target=bg_thread)
+ t.start()
+ bg_threads.append(t)
+
+ for i in range(100):
+ threading.setprofile_all_threads(my_profile)
+ threading.setprofile_all_threads(None)
+
+ done.set()
+ for t in bg_threads:
+ t.join()
+
+
class TraceBuf:
def __init__(self):
self.traces = []
--- /dev/null
+Fix a crash in the :term:`free threading` build when disabling profiling or tracing
+across all threads with :c:func:`PyEval_SetProfileAllThreads` or
+:c:func:`PyEval_SetTraceAllThreads` or their Python equivalents
+:func:`threading.settrace_all_threads` and :func:`threading.setprofile_all_threads`.
}
}
+ _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
}
}
+ _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