11import unittest
22import os
33import textwrap
4+ import contextlib
45import importlib
56import sys
67import socket
@@ -215,36 +216,13 @@ def requires_subinterpreters(meth):
215216# Simple wrapper functions for RemoteUnwinder
216217# ============================================================================
217218
218- # Errors that can occur transiently when reading process memory without synchronization
219- RETRIABLE_ERRORS = (
220- "Bad address" ,
221- "Task list appears corrupted" ,
222- "Invalid linked list structure reading remote memory" ,
223- "Invalid string length" ,
224- "Unknown error reading memory" ,
225- "Unhandled frame owner" ,
226- "Failed to parse initial frame" ,
227- "Failed to process frame chain" ,
228- "Failed to unwind stack" ,
229- "process_vm_readv" ,
230- )
231-
232-
233- def _is_retriable_error (exc ):
234- """Check if an exception is a transient error that should be retried."""
235- msg = str (exc )
236- return any (msg .startswith (err ) or err in msg for err in RETRIABLE_ERRORS )
237-
238-
239219def get_stack_trace (pid ):
240220 for _ in busy_retry (SHORT_TIMEOUT ):
241221 try :
242222 unwinder = RemoteUnwinder (pid , all_threads = True , debug = True )
243223 return unwinder .get_stack_trace ()
244224 except RuntimeError as e :
245- if _is_retriable_error (e ):
246- continue
247- raise
225+ continue
248226 raise RuntimeError ("Failed to get stack trace after retries" )
249227
250228
@@ -254,9 +232,7 @@ def get_async_stack_trace(pid):
254232 unwinder = RemoteUnwinder (pid , debug = True )
255233 return unwinder .get_async_stack_trace ()
256234 except RuntimeError as e :
257- if _is_retriable_error (e ):
258- continue
259- raise
235+ continue
260236 raise RuntimeError ("Failed to get async stack trace after retries" )
261237
262238
@@ -266,9 +242,7 @@ def get_all_awaited_by(pid):
266242 unwinder = RemoteUnwinder (pid , debug = True )
267243 return unwinder .get_all_awaited_by ()
268244 except RuntimeError as e :
269- if _is_retriable_error (e ):
270- continue
271- raise
245+ continue
272246 raise RuntimeError ("Failed to get all awaited_by after retries" )
273247
274248
@@ -2270,16 +2244,13 @@ def make_unwinder(cache_frames=True):
22702244 def _get_frames_with_retry (self , unwinder , required_funcs ):
22712245 """Get frames containing required_funcs, with retry for transient errors."""
22722246 for _ in range (MAX_TRIES ):
2273- try :
2247+ with contextlib . suppress ( OSError , RuntimeError ) :
22742248 traces = unwinder .get_stack_trace ()
22752249 for interp in traces :
22762250 for thread in interp .threads :
22772251 funcs = {f .funcname for f in thread .frame_info }
22782252 if required_funcs .issubset (funcs ):
22792253 return thread .frame_info
2280- except (OSError , RuntimeError ) as e :
2281- if not _is_retriable_error (e ):
2282- raise
22832254 time .sleep (0.1 )
22842255 return None
22852256
@@ -2819,12 +2790,12 @@ def foo2():
28192790 for i in range (4 ):
28202791 # Extract first message from buffer
28212792 msg , sep , buffer = buffer .partition (b"\n " )
2822- self .assertIn (msg , dispatch , f"Unexpected message: { msg } " )
2793+ self .assertIn (msg , dispatch , f"Unexpected message: { msg !r } " )
28232794
28242795 # Sample frames for the thread at this sync point
28252796 required_funcs = dispatch [msg ]
28262797 frames = self ._get_frames_with_retry (unwinder , required_funcs )
2827- self .assertIsNotNone (frames , f"Thread not found for { msg } " )
2798+ self .assertIsNotNone (frames , f"Thread not found for { msg !r } " )
28282799 results [msg ] = [f .funcname for f in frames ]
28292800
28302801 # Release thread and wait for next message (if not last)
0 commit comments