@@ -2336,21 +2336,39 @@ def get_trace_with_opcodes(pid):
23362336 def test_tlbc_cache_refresh_after_growth (self ):
23372337 # Reproducer from gh-157660.
23382338 script = textwrap .dedent ("""\
2339- import os, threading
2339+ import os, sys, threading
23402340 from _remote_debugging import RemoteUnwinder
23412341 from test import support
23422342
2343- go = threading.Event()
2344- stop = threading.Event()
2343+ go = threading.Lock()
2344+ stop = threading.Lock()
2345+ go.acquire()
2346+ stop.acquire()
23452347
23462348 def leaf():
2347- stop.wait ()
2349+ stop.acquire ()
23482350
23492351 def wait_for_leaf_frames(u, expected_count):
23502352 for _ in support.sleeping_retry(
23512353 support.SHORT_TIMEOUT,
23522354 f"Expected {expected_count} leaf frames",
23532355 ):
2356+ # Wait until the workers have entered their native lock
2357+ # calls, so sampling cannot race with Python frame changes.
2358+ frames = sys._current_frames()
2359+ frames.pop(threading.get_ident())
2360+ if len(frames) != 18:
2361+ continue
2362+ leaves = [f for f in frames.values()
2363+ if f.f_code is leaf.__code__]
2364+ if (len(leaves) != expected_count or
2365+ any(f.f_lineno != leaf.__code__.co_firstlineno + 1
2366+ for f in leaves)):
2367+ continue
2368+ if any(f.f_code not in (leaf.__code__, start_leaf.__code__,
2369+ threading.Thread.run.__code__)
2370+ for f in frames.values()):
2371+ continue
23542372 try:
23552373 traces = u.get_stack_trace()
23562374 except RuntimeError as exc:
@@ -2367,12 +2385,13 @@ def wait_for_leaf_frames(u, expected_count):
23672385
23682386 threading.Thread(target=leaf, daemon=True).start()
23692387 for _ in range(16):
2370- threading.Thread(target=stop.wait, daemon=True).start()
2371- threading.Thread(target=lambda: (go.wait(), leaf()), daemon=True).start()
2388+ threading.Thread(target=stop.acquire, daemon=True).start()
2389+ start_leaf = lambda: (go.acquire(), leaf())
2390+ threading.Thread(target=start_leaf, daemon=True).start()
23722391
23732392 u = RemoteUnwinder(os.getpid(), all_threads=True, cache_frames=False)
23742393 wait_for_leaf_frames(u, 1)
2375- go.set ()
2394+ go.release ()
23762395 wait_for_leaf_frames(u, 2)
23772396 """ )
23782397 result = subprocess .run (
@@ -2395,14 +2414,16 @@ def wait_for_leaf_frames(u, expected_count):
23952414 def test_tlbc_cache_refresh_after_slot_fill (self ):
23962415 # Reproducer from gh-157660.
23972416 script = textwrap .dedent ("""\
2398- import os, threading
2417+ import os, sys, threading
23992418 from _remote_debugging import RemoteUnwinder
24002419
2401- go = threading.Event()
2402- stop = threading.Event()
2420+ go = threading.Lock()
2421+ stop = threading.Lock()
2422+ go.acquire()
2423+ stop.acquire()
24032424
24042425 def leaf():
2405- stop.wait ()
2426+ stop.acquire ()
24062427
24072428 from test import support
24082429
@@ -2411,6 +2432,22 @@ def lines(u, expected_count):
24112432 support.SHORT_TIMEOUT,
24122433 f"Expected {expected_count} leaf frames",
24132434 ):
2435+ # Wait until the workers have entered their native lock
2436+ # calls, so sampling cannot race with Python frame changes.
2437+ frames = sys._current_frames()
2438+ frames.pop(threading.get_ident())
2439+ if len(frames) != 2:
2440+ continue
2441+ leaves = [f for f in frames.values()
2442+ if f.f_code is leaf.__code__]
2443+ if (len(leaves) != expected_count or
2444+ any(f.f_lineno != leaf.__code__.co_firstlineno + 1
2445+ for f in leaves)):
2446+ continue
2447+ if any(f.f_code not in (leaf.__code__, start_leaf.__code__,
2448+ threading.Thread.run.__code__)
2449+ for f in frames.values()):
2450+ continue
24142451 try:
24152452 traces = u.get_stack_trace()
24162453 except RuntimeError as exc:
@@ -2429,13 +2466,14 @@ def lines(u, expected_count):
24292466 return result
24302467
24312468 threading.Thread(target=leaf, daemon=True).start()
2432- threading.Thread(target=lambda: (go.wait(), leaf()), daemon=True).start()
2469+ start_leaf = lambda: (go.acquire(), leaf())
2470+ threading.Thread(target=start_leaf, daemon=True).start()
24332471 u = RemoteUnwinder(os.getpid(), all_threads=True, cache_frames=False)
24342472 before = lines(u, 1)
2435- assert before == [8 ], before
2436- go.set ()
2473+ assert before == [10 ], before
2474+ go.release ()
24372475 cached = lines(u, 2)
2438- assert cached == [8, 8 ], cached
2476+ assert cached == [10, 10 ], cached
24392477 """ )
24402478 result = subprocess .run (
24412479 [sys .executable , "-X" , "gil=0" , "-X" , "tlbc=1" , "-c" , script ],
0 commit comments