Skip to content

Commit 28da1fb

Browse files
authored
gh-142368: Fix transient error handling in inspection tests (#143093)
1 parent 81c8eb8 commit 28da1fb

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

Lib/test/test_external_inspection.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737

3838
# Maximum number of retry attempts for operations that may fail transiently
3939
MAX_TRIES = 10
40+
RETRY_DELAY = 0.1
41+
42+
# Exceptions that can occur transiently when reading from a live process
43+
TRANSIENT_ERRORS = (OSError, RuntimeError, UnicodeDecodeError)
4044

4145
try:
4246
from concurrent import interpreters
@@ -1713,7 +1717,7 @@ def main_work():
17131717
)
17141718
if found:
17151719
break
1716-
time.sleep(0.1)
1720+
time.sleep(RETRY_DELAY)
17171721
else:
17181722
self.fail(
17191723
"Main thread did not start its busy work on time"
@@ -2505,7 +2509,11 @@ def _check_exception_status(self, p, thread_tid, expect_exception):
25052509
# Collect multiple samples for reliability
25062510
results = []
25072511
for _ in range(MAX_TRIES):
2508-
traces = unwinder.get_stack_trace()
2512+
try:
2513+
traces = unwinder.get_stack_trace()
2514+
except TRANSIENT_ERRORS:
2515+
time.sleep(RETRY_DELAY)
2516+
continue
25092517
statuses = self._get_thread_statuses(traces)
25102518

25112519
if thread_tid in statuses:
@@ -2515,7 +2523,7 @@ def _check_exception_status(self, p, thread_tid, expect_exception):
25152523
if len(results) >= 3:
25162524
break
25172525

2518-
time.sleep(0.2)
2526+
time.sleep(RETRY_DELAY)
25192527

25202528
# Check majority of samples match expected
25212529
if not results:
@@ -2648,14 +2656,14 @@ def make_unwinder(cache_frames=True):
26482656
def _get_frames_with_retry(self, unwinder, required_funcs):
26492657
"""Get frames containing required_funcs, with retry for transient errors."""
26502658
for _ in range(MAX_TRIES):
2651-
with contextlib.suppress(OSError, RuntimeError):
2659+
with contextlib.suppress(*TRANSIENT_ERRORS):
26522660
traces = unwinder.get_stack_trace()
26532661
for interp in traces:
26542662
for thread in interp.threads:
26552663
funcs = {f.funcname for f in thread.frame_info}
26562664
if required_funcs.issubset(funcs):
26572665
return thread.frame_info
2658-
time.sleep(0.1)
2666+
time.sleep(RETRY_DELAY)
26592667
return None
26602668

26612669
def _sample_frames(
@@ -2674,7 +2682,7 @@ def _sample_frames(
26742682
frames = self._get_frames_with_retry(unwinder, required_funcs)
26752683
if frames and len(frames) >= expected_frames:
26762684
break
2677-
time.sleep(0.1)
2685+
time.sleep(RETRY_DELAY)
26782686
client_socket.sendall(send_ack)
26792687
return frames
26802688

0 commit comments

Comments
 (0)