From 9127013b56488606735cbf41c4e6cf2a7bcf11d2 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Mon, 24 Nov 2025 18:46:59 +0100 Subject: [PATCH] [3.13] gh-129441: Fix some flakiness in test_instrumentation (gh-141881) (gh-141914) Most of the `self.assertTrue(self.called)` checks are flaky because the worker threads may sometimes finish before the main thread calls `self.during_threads()`. (cherry picked from commit 71126ab19c76d8227fc3b9c7c59b957ca82af4dd) Co-authored-by: Sam Gross --- .../test_free_threading/test_monitoring.py | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/Lib/test/test_free_threading/test_monitoring.py b/Lib/test/test_free_threading/test_monitoring.py index 1375e8e0c364..4e8ee2e2ac06 100644 --- a/Lib/test/test_free_threading/test_monitoring.py +++ b/Lib/test/test_free_threading/test_monitoring.py @@ -9,7 +9,7 @@ import weakref from sys import monitoring from test.support import threading_helper -from threading import Thread, _PyRLock +from threading import Thread, _PyRLock, Barrier from unittest import TestCase @@ -34,10 +34,10 @@ class InstrumentationMultiThreadedMixin: return n return self.work(n - 1, funcs) + self.work(n - 2, funcs) - def start_work(self, n, funcs): + def start_work(self, n, funcs, barrier): # With the GIL builds we need to make sure that the hooks have # a chance to run as it's possible to run w/o releasing the GIL. - time.sleep(0.1) + barrier.wait() self.work(n, funcs) def after_test(self): @@ -52,14 +52,16 @@ class InstrumentationMultiThreadedMixin: exec("def f(): pass", x) funcs.append(x["f"]) + barrier = Barrier(self.thread_count + 1) threads = [] for i in range(self.thread_count): # Each thread gets a copy of the func list to avoid contention - t = Thread(target=self.start_work, args=(self.fib, list(funcs))) + t = Thread(target=self.start_work, args=(self.fib, list(funcs), barrier)) t.start() threads.append(t) self.after_threads() + barrier.wait() while True: any_alive = False @@ -119,7 +121,6 @@ class MonitoringMultiThreaded( def setUp(self): super().setUp() self.set = False - self.called = False monitoring.register_callback( self.tool_id, monitoring.events.LINE, self.callback ) @@ -129,10 +130,7 @@ class MonitoringMultiThreaded( super().tearDown() def callback(self, *args): - self.called = True - - def after_test(self): - self.assertTrue(self.called) + pass def during_threads(self): if self.set: @@ -150,16 +148,11 @@ class SetTraceMultiThreaded(InstrumentationMultiThreadedMixin, TestCase): def setUp(self): self.set = False - self.called = False - - def after_test(self): - self.assertTrue(self.called) def tearDown(self): sys.settrace(None) def trace_func(self, frame, event, arg): - self.called = True return self.trace_func def during_threads(self): @@ -176,16 +169,11 @@ class SetProfileMultiThreaded(InstrumentationMultiThreadedMixin, TestCase): def setUp(self): self.set = False - self.called = False - - def after_test(self): - self.assertTrue(self.called) def tearDown(self): sys.setprofile(None) def trace_func(self, frame, event, arg): - self.called = True return self.trace_func def during_threads(self): @@ -202,16 +190,11 @@ class SetProfileAllThreadsMultiThreaded(InstrumentationMultiThreadedMixin, TestC def setUp(self): self.set = False - self.called = False - - def after_test(self): - self.assertTrue(self.called) def tearDown(self): threading.setprofile_all_threads(None) def trace_func(self, frame, event, arg): - self.called = True return self.trace_func def during_threads(self): -- 2.47.3