[3.13] gh-137400: Fix a crash when disabling profiling across all threads (gh-137471) (gh-137649)

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.
(cherry picked from commit 362692852f)
This commit is contained in:
Sam Gross 2025-08-11 12:07:21 -04:00 committed by GitHub
parent 63a9494878
commit e236568c0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 47 additions and 2 deletions

View file

@ -2,6 +2,7 @@
environment to verify things are thread-safe in a free-threaded build"""
import sys
import threading
import time
import unittest
import weakref
@ -192,6 +193,40 @@ def during_threads(self):
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()
@threading_helper.requires_working_threading()
class MonitoringMisc(MonitoringTestMixin, TestCase):
def register_callback(self):