3737
3838# Maximum number of retry attempts for operations that may fail transiently
3939MAX_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
4145try :
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