2020#include "pycore_opcode.h" // EXTRA_CASES
2121#include "pycore_pyerrors.h" // _PyErr_Fetch()
2222#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
23+ #include "pycore_refcnt.h" // _PyObjectQueue
2324#include "pycore_pystate.h" // _PyInterpreterState_GET()
2425#include "pycore_range.h" // _PyRangeIterObject
2526#include "pycore_sliceobject.h" // _PyBuildSlice_ConsumeRefs
@@ -2571,6 +2572,28 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
25712572 return result ;
25722573}
25732574
2575+ static PyObject *
2576+ thread_set_profile (PyThreadState * tstate , Py_tracefunc func , PyObject * arg )
2577+ {
2578+ tstate -> c_profilefunc = func ;
2579+ PyObject * old_profileobj = tstate -> c_profileobj ;
2580+ tstate -> c_profileobj = Py_XNewRef (arg );
2581+ /* Flag that tracing or profiling is turned on */
2582+ _PyThreadState_UpdateTracingState (tstate );
2583+ return old_profileobj ;
2584+ }
2585+
2586+ static PyObject *
2587+ thread_set_trace (PyThreadState * tstate , Py_tracefunc func , PyObject * arg )
2588+ {
2589+ tstate -> c_tracefunc = func ;
2590+ PyObject * old_traceobj = tstate -> c_traceobj ;
2591+ tstate -> c_traceobj = Py_XNewRef (arg );
2592+ /* Flag that tracing or profiling is turned on */
2593+ _PyThreadState_UpdateTracingState (tstate );
2594+ return old_traceobj ;
2595+ }
2596+
25742597int
25752598_PyEval_SetProfile (PyThreadState * tstate , Py_tracefunc func , PyObject * arg )
25762599{
@@ -2585,11 +2608,7 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
25852608 return -1 ;
25862609 }
25872610
2588- tstate -> c_profilefunc = func ;
2589- PyObject * old_profileobj = tstate -> c_profileobj ;
2590- tstate -> c_profileobj = Py_XNewRef (arg );
2591- /* Flag that tracing or profiling is turned on */
2592- _PyThreadState_UpdateTracingState (tstate );
2611+ PyObject * old_profileobj = thread_set_profile (tstate , func , arg );
25932612
25942613 // gh-98257: Only call Py_XDECREF() once the new profile function is fully
25952614 // set, so it's safe to call sys.setprofile() again (reentrant call).
@@ -2612,20 +2631,32 @@ void
26122631PyEval_SetProfileAllThreads (Py_tracefunc func , PyObject * arg )
26132632{
26142633 PyThreadState * this_tstate = _PyThreadState_GET ();
2615- PyInterpreterState * interp = this_tstate -> interp ;
2634+ if (_PySys_Audit (this_tstate , "sys.setprofile" , NULL ) < 0 ) {
2635+ /* Log _PySys_Audit() error */
2636+ _PyErr_WriteUnraisableMsg ("in PyEval_SetProfileAllThreads" , NULL );
2637+ }
26162638
2639+ PyInterpreterState * interp = this_tstate -> interp ;
26172640 _PyRuntimeState * runtime = & _PyRuntime ;
2641+
2642+ _PyObjectQueue * queue = NULL ;
2643+
2644+ _PyRuntimeState_StopTheWorld (& _PyRuntime );
26182645 HEAD_LOCK (runtime );
26192646 PyThreadState * ts = PyInterpreterState_ThreadHead (interp );
2620- HEAD_UNLOCK (runtime );
2621-
26222647 while (ts ) {
2623- if (_PyEval_SetProfile (ts , func , arg ) < 0 ) {
2624- _PyErr_WriteUnraisableMsg ("in PyEval_SetProfileAllThreads" , NULL );
2648+ PyObject * old_profileobj = thread_set_profile (ts , func , arg );
2649+ if (old_profileobj ) {
2650+ _PyObjectQueue_Push (& queue , old_profileobj );
26252651 }
2626- HEAD_LOCK (runtime );
26272652 ts = PyThreadState_Next (ts );
2628- HEAD_UNLOCK (runtime );
2653+ }
2654+ HEAD_UNLOCK (runtime );
2655+ _PyRuntimeState_StartTheWorld (& _PyRuntime );
2656+
2657+ PyObject * old_profileobj ;
2658+ _PyObjectQueue_ForEach (& queue , old_profileobj ) {
2659+ Py_DECREF (old_profileobj );
26292660 }
26302661}
26312662
@@ -2643,16 +2674,11 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
26432674 return -1 ;
26442675 }
26452676
2646- tstate -> c_tracefunc = func ;
2647- PyObject * old_traceobj = tstate -> c_traceobj ;
2648- tstate -> c_traceobj = Py_XNewRef (arg );
2649- /* Flag that tracing or profiling is turned on */
2650- _PyThreadState_UpdateTracingState (tstate );
2677+ PyObject * old_traceobj = thread_set_trace (tstate , func , arg );
26512678
26522679 // gh-98257: Only call Py_XDECREF() once the new trace function is fully
26532680 // set, so it's safe to call sys.settrace() again (reentrant call).
26542681 Py_XDECREF (old_traceobj );
2655-
26562682 return 0 ;
26572683}
26582684
@@ -2670,20 +2696,37 @@ void
26702696PyEval_SetTraceAllThreads (Py_tracefunc func , PyObject * arg )
26712697{
26722698 PyThreadState * this_tstate = _PyThreadState_GET ();
2673- PyInterpreterState * interp = this_tstate -> interp ;
26742699
2700+ if (_PySys_Audit (this_tstate , "sys.settrace" , NULL ) < 0 ) {
2701+ /* Log _PySys_Audit() error */
2702+ _PyErr_WriteUnraisableMsg ("in PyEval_SetTraceAllThreads" , NULL );
2703+ }
2704+
2705+ PyInterpreterState * interp = this_tstate -> interp ;
26752706 _PyRuntimeState * runtime = & _PyRuntime ;
2707+
2708+ _PyObjectQueue * queue = NULL ;
2709+
2710+ _PyMutex_lock (& _PyRuntime .stoptheworld_mutex );
2711+ _PyRuntimeState_StopTheWorld (& _PyRuntime );
2712+
26762713 HEAD_LOCK (runtime );
26772714 PyThreadState * ts = PyInterpreterState_ThreadHead (interp );
2678- HEAD_UNLOCK (runtime );
2679-
26802715 while (ts ) {
2681- if (_PyEval_SetTrace (ts , func , arg ) < 0 ) {
2682- _PyErr_WriteUnraisableMsg ("in PyEval_SetTraceAllThreads" , NULL );
2716+ PyObject * old_traceobj = thread_set_trace (ts , func , arg );
2717+ if (old_traceobj ) {
2718+ _PyObjectQueue_Push (& queue , old_traceobj );
26832719 }
2684- HEAD_LOCK (runtime );
26852720 ts = PyThreadState_Next (ts );
2686- HEAD_UNLOCK (runtime );
2721+ }
2722+ HEAD_UNLOCK (runtime );
2723+
2724+ _PyRuntimeState_StartTheWorld (& _PyRuntime );
2725+ _PyMutex_unlock (& _PyRuntime .stoptheworld_mutex );
2726+
2727+ PyObject * old_traceobj ;
2728+ _PyObjectQueue_ForEach (& queue , old_traceobj ) {
2729+ Py_DECREF (old_traceobj );
26872730 }
26882731}
26892732
0 commit comments