1616#endif
1717#include "Python.h"
1818#include <internal/pycore_debug_offsets.h> // _Py_DebugOffsets
19+ #include <internal/pycore_global_objects.h>
1920#include <internal/pycore_frame.h> // FRAME_SUSPENDED_YIELD_FROM
2021#include <internal/pycore_interpframe.h> // FRAME_OWNED_BY_CSTACK
2122#include <internal/pycore_llist.h> // struct llist_node
@@ -804,7 +805,7 @@ static int append_awaited_by(RemoteUnwinderObject *unwinder, unsigned long tid,
804805#define set_exception_cause (unwinder , exc_type , message ) \
805806 do { \
806807 assert(PyErr_Occurred() && "function returned -1 without setting exception"); \
807- if (unwinder->debug && !_Py_RemoteDebug_HasPermissionError ()) { \
808+ if (unwinder->debug && !_Py_RemoteDebug_IsFatalReadError ()) { \
808809 _set_debug_exception_cause(exc_type, message); \
809810 } \
810811 } while (0)
@@ -2257,13 +2258,18 @@ parse_code_object(RemoteUnwinderObject *unwinder,
22572258 uintptr_t * previous_frame ,
22582259 int32_t tlbc_index )
22592260{
2261+ _Py_DECLARE_STR (unknown_function , "<unknown function>" );
2262+ _Py_DECLARE_STR (unknown_file , "<unknown file>" );
2263+ _Py_DECLARE_STR (unreadable_frame , "<unreadable frame>" );
2264+
22602265 void * key = (void * )address ;
22612266 CachedCodeMetadata * meta = NULL ;
22622267 PyObject * func = NULL ;
22632268 PyObject * file = NULL ;
22642269 PyObject * linetable = NULL ;
22652270 PyObject * lineno = NULL ;
22662271 PyObject * tuple = NULL ;
2272+ int code_metadata_incomplete = 0 ;
22672273
22682274#ifdef Py_GIL_DISABLED
22692275 // In free threading builds, code object addresses might have the low bit set
@@ -2282,29 +2288,50 @@ parse_code_object(RemoteUnwinderObject *unwinder,
22822288 if (_Py_RemoteDebug_PagedReadRemoteMemory (
22832289 & unwinder -> handle , real_address , SIZEOF_CODE_OBJ , code_object ) < 0 )
22842290 {
2285- set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to read code object" );
2286- goto error ;
2291+ if (_Py_RemoteDebug_IsFatalReadError ()) {
2292+ goto error ;
2293+ }
2294+ PyErr_Clear ();
2295+ func = Py_NewRef (& _Py_STR (unreadable_frame ));
2296+ file = Py_NewRef (_Py_LATIN1_CHR ('~' ));
2297+ goto degraded ;
22872298 }
22882299
22892300 func = read_py_str (unwinder ,
22902301 GET_MEMBER (uintptr_t , code_object , unwinder -> debug_offsets .code_object .qualname ), 1024 );
22912302 if (!func ) {
2292- set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to read function name from code object" );
2293- goto error ;
2303+ if (_Py_RemoteDebug_IsFatalReadError ()) {
2304+ goto error ;
2305+ }
2306+ PyErr_Clear ();
2307+ func = Py_NewRef (& _Py_STR (unknown_function ));
2308+ code_metadata_incomplete = 1 ;
22942309 }
22952310
22962311 file = read_py_str (unwinder ,
22972312 GET_MEMBER (uintptr_t , code_object , unwinder -> debug_offsets .code_object .filename ), 1024 );
22982313 if (!file ) {
2299- set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to read filename from code object" );
2300- goto error ;
2314+ if (_Py_RemoteDebug_IsFatalReadError ()) {
2315+ goto error ;
2316+ }
2317+ PyErr_Clear ();
2318+ file = Py_NewRef (& _Py_STR (unknown_file ));
2319+ code_metadata_incomplete = 1 ;
2320+ }
2321+
2322+ if (code_metadata_incomplete ) {
2323+ goto degraded ;
23012324 }
23022325
23032326 linetable = read_py_bytes (unwinder ,
2304- GET_MEMBER (uintptr_t , code_object , unwinder -> debug_offsets .code_object .linetable ), 4096 );
2327+ GET_MEMBER (uintptr_t , code_object , unwinder -> debug_offsets .code_object .linetable ),
2328+ 4096 );
23052329 if (!linetable ) {
2306- set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to read linetable from code object" );
2307- goto error ;
2330+ if (_Py_RemoteDebug_IsFatalReadError ()) {
2331+ goto error ;
2332+ }
2333+ PyErr_Clear ();
2334+ goto degraded ;
23082335 }
23092336
23102337 meta = PyMem_RawMalloc (sizeof (CachedCodeMetadata ));
@@ -2434,6 +2461,19 @@ parse_code_object(RemoteUnwinderObject *unwinder,
24342461 * result = tuple ;
24352462 return 0 ;
24362463
2464+ degraded : {
2465+ RemoteDebuggingState * state = RemoteDebugging_GetStateFromObject ((PyObject * )unwinder );
2466+ PyObject * degraded_tuple = PyStructSequence_New (state -> FrameInfo_Type );
2467+ if (!degraded_tuple ) {
2468+ goto error ;
2469+ }
2470+ PyStructSequence_SetItem (degraded_tuple , 0 , file );
2471+ PyStructSequence_SetItem (degraded_tuple , 1 , Py_NewRef (Py_None ));
2472+ PyStructSequence_SetItem (degraded_tuple , 2 , func );
2473+ * result = degraded_tuple ;
2474+ return 0 ;
2475+ }
2476+
24372477error :
24382478 Py_XDECREF (func );
24392479 Py_XDECREF (file );
0 commit comments