@@ -2363,50 +2363,42 @@ def test_tlbc_cache_refresh_after_growth(self):
23632363 script = textwrap .dedent ("""\
23642364 import os, threading
23652365 from _remote_debugging import RemoteUnwinder
2366- from _queue import SimpleQueue
23672366 from test import support
23682367
2369- go = threading.Lock()
2370- stop = threading.Lock()
2371- go.acquire()
2372- stop.acquire()
2373- ready = SimpleQueue()
2368+ go = threading.Event()
2369+ stop = threading.Event()
23742370
23752371 def leaf():
2376- ready.put(None)
2377- stop.acquire()
2378-
2379- def start_leaf():
2380- ready.put(None)
2381- go.acquire()
2382- leaf()
2383-
2384- def park():
2385- ready.put(None)
2386- stop.acquire()
2387-
2388- def leaf_count(u):
2389- return sum(
2390- f.funcname == "leaf"
2391- for i in u.get_stack_trace()
2392- for t in i.threads for f in t.frame_info
2393- )
2372+ stop.wait()
2373+
2374+ def wait_for_leaf_frames(u, expected_count):
2375+ for _ in support.sleeping_retry(
2376+ support.SHORT_TIMEOUT,
2377+ f"Expected {expected_count} leaf frames",
2378+ ):
2379+ try:
2380+ traces = u.get_stack_trace()
2381+ except RuntimeError as exc:
2382+ if str(exc) != "Failed to parse initial frame in chain":
2383+ raise
2384+ continue
2385+ count = sum(
2386+ f.funcname == "leaf"
2387+ for i in traces
2388+ for t in i.threads for f in t.frame_info
2389+ )
2390+ if count == expected_count:
2391+ return
23942392
2395- # SimpleQueue.put() and Lock.acquire() do not push Python frames.
2396- # Once notified, the worker's stack stays stable until go is released.
23972393 threading.Thread(target=leaf, daemon=True).start()
2398- ready.get(timeout=support.SHORT_TIMEOUT)
23992394 for _ in range(16):
2400- threading.Thread(target=park, daemon=True).start()
2401- ready.get(timeout=support.SHORT_TIMEOUT)
2402- threading.Thread(target=start_leaf, daemon=True).start()
2403- ready.get(timeout=support.SHORT_TIMEOUT)
2395+ threading.Thread(target=stop.wait, daemon=True).start()
2396+ threading.Thread(target=lambda: (go.wait(), leaf()), daemon=True).start()
24042397
24052398 u = RemoteUnwinder(os.getpid(), all_threads=True, cache_frames=False)
2406- assert leaf_count(u) == 1
2407- go.release()
2408- ready.get(timeout=support.SHORT_TIMEOUT)
2409- assert leaf_count(u) == 2
2399+ wait_for_leaf_frames(u, 1)
2400+ go.set()
2401+ wait_for_leaf_frames(u, 2)
24102402 """ )
24112403 result = subprocess .run (
24122404 [sys .executable , "-X" , "gil=0" , "-X" , "tlbc=1" , "-c" , script ],
@@ -2430,49 +2422,45 @@ def test_tlbc_cache_refresh_after_slot_fill(self):
24302422 script = textwrap .dedent ("""\
24312423 import os, threading
24322424 from _remote_debugging import RemoteUnwinder
2433- from _queue import SimpleQueue
24342425
2435- go = threading.Lock()
2436- stop = threading.Lock()
2437- go.acquire()
2438- stop.acquire()
2439- ready = SimpleQueue()
2426+ go = threading.Event()
2427+ stop = threading.Event()
24402428
24412429 def leaf():
2442- ready.put(None)
2443- stop.acquire()
2444-
2445- def start_leaf():
2446- ready.put(None)
2447- go.acquire()
2448- leaf()
2430+ stop.wait()
24492431
24502432 from test import support
24512433
2452- def lines(u):
2453- return sorted(
2454- f.location.lineno
2455- for i in u.get_stack_trace()
2456- for t in i.threads for f in t.frame_info
2457- if f.funcname == "leaf"
2458- )
2434+ def lines(u, expected_count):
2435+ for _ in support.sleeping_retry(
2436+ support.SHORT_TIMEOUT,
2437+ f"Expected {expected_count} leaf frames",
2438+ ):
2439+ try:
2440+ traces = u.get_stack_trace()
2441+ except RuntimeError as exc:
2442+ if str(exc) != "Failed to parse initial frame in chain":
2443+ raise
2444+ continue
2445+ result = sorted(
2446+ f.location.lineno
2447+ for i in traces
2448+ for t in i.threads for f in t.frame_info
2449+ if f.funcname == "leaf"
2450+ )
2451+ # A new frame can still point at the function definition.
2452+ if (len(result) == expected_count and
2453+ leaf.__code__.co_firstlineno not in result):
2454+ return result
24592455
2460- # SimpleQueue.put() and Lock.acquire() do not push Python frames.
2461- # Once notified, the worker's stack stays stable until go is released.
24622456 threading.Thread(target=leaf, daemon=True).start()
2463- ready.get(timeout=support.SHORT_TIMEOUT)
2464- threading.Thread(target=start_leaf, daemon=True).start()
2465- ready.get(timeout=support.SHORT_TIMEOUT)
2457+ threading.Thread(target=lambda: (go.wait(), leaf()), daemon=True).start()
24662458 u = RemoteUnwinder(os.getpid(), all_threads=True, cache_frames=False)
2467- before = lines(u)
2468- # The notification can be observed before put() returns, so either
2469- # line in leaf() is a valid sample.
2470- assert before in ([12], [13]), before
2471- go.release()
2472- ready.get(timeout=support.SHORT_TIMEOUT)
2473- cached = lines(u)
2474- assert len(cached) == 2, cached
2475- assert all(line in (12, 13) for line in cached), cached
2459+ before = lines(u, 1)
2460+ assert before == [8], before
2461+ go.set()
2462+ cached = lines(u, 2)
2463+ assert cached == [8, 8], cached
24762464 """ )
24772465 result = subprocess .run (
24782466 [sys .executable , "-X" , "gil=0" , "-X" , "tlbc=1" , "-c" , script ],
0 commit comments