@@ -238,13 +238,14 @@ parse_task_name(
238238 * ============================================================================ */
239239
240240static int
241- handle_yield_from_frame (
241+ get_awaited_coro_address (
242242 RemoteUnwinderObject * unwinder ,
243243 uintptr_t gi_iframe_addr ,
244244 uintptr_t gen_type_addr ,
245- PyObject * render_to ,
246- size_t depth
245+ uintptr_t * next_coro
247246) {
247+ * next_coro = 0 ;
248+
248249 // Read the entire interpreter frame at once
249250 char iframe [SIZEOF_INTERP_FRAME ];
250251 int err = _Py_RemoteDebug_PagedReadRemoteMemory (
@@ -300,80 +301,80 @@ handle_yield_from_frame(
300301 doesn't match the type of whatever it points to
301302 in its cr_await.
302303 */
303- err = parse_coro_chain (unwinder , gi_await_addr , render_to ,
304- depth + 1 );
305- if (err ) {
306- set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to parse coroutine chain in yield_from" );
307- return -1 ;
308- }
304+ * next_coro = gi_await_addr ;
309305 }
310306 }
311307 }
312308
313309 return 0 ;
314310}
315311
316- int
312+ static int
317313parse_coro_chain (
318314 RemoteUnwinderObject * unwinder ,
319315 uintptr_t coro_address ,
320- PyObject * render_to ,
321- size_t depth
316+ PyObject * render_to
322317) {
323318 assert ((void * )coro_address != NULL );
324319
325- if (depth >= MAX_FRAME_CHAIN_DEPTH ) {
326- PyErr_SetString (PyExc_RuntimeError ,
327- "Too many coroutine frames (possible infinite loop)" );
328- set_exception_cause (unwinder , PyExc_RuntimeError ,
329- "Coroutine chain depth limit exceeded" );
330- return -1 ;
331- }
320+ for (size_t depth = 0 ; (void * )coro_address != NULL ; depth ++ ) {
321+ if (depth >= MAX_FRAME_CHAIN_DEPTH ) {
322+ PyErr_SetString (PyExc_RuntimeError ,
323+ "Too many coroutine frames (possible infinite loop)" );
324+ set_exception_cause (unwinder , PyExc_RuntimeError ,
325+ "Coroutine chain depth limit exceeded" );
326+ return -1 ;
327+ }
332328
333- // Read the entire generator object at once
334- char gen_object [SIZEOF_GEN_OBJ ];
335- int err = _Py_RemoteDebug_PagedReadRemoteMemory (
336- & unwinder -> handle ,
337- coro_address ,
338- SIZEOF_GEN_OBJ ,
339- gen_object );
340- if (err < 0 ) {
341- set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to read generator object in coro chain" );
342- return -1 ;
343- }
329+ // Read the entire generator object at once
330+ char gen_object [SIZEOF_GEN_OBJ ];
331+ int err = _Py_RemoteDebug_PagedReadRemoteMemory (
332+ & unwinder -> handle ,
333+ coro_address ,
334+ SIZEOF_GEN_OBJ ,
335+ gen_object );
336+ if (err < 0 ) {
337+ set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to read generator object in coro chain" );
338+ return -1 ;
339+ }
344340
345- int8_t frame_state = GET_MEMBER (int8_t , gen_object , unwinder -> debug_offsets .gen_object .gi_frame_state );
346- if (frame_state == FRAME_CLEARED ) {
347- return 0 ;
348- }
341+ int8_t frame_state = GET_MEMBER (int8_t , gen_object , unwinder -> debug_offsets .gen_object .gi_frame_state );
342+ if (frame_state == FRAME_CLEARED ) {
343+ return 0 ;
344+ }
349345
350- uintptr_t gen_type_addr = GET_MEMBER (uintptr_t , gen_object , unwinder -> debug_offsets .pyobject .ob_type );
346+ uintptr_t gen_type_addr = GET_MEMBER (uintptr_t , gen_object , unwinder -> debug_offsets .pyobject .ob_type );
351347
352- PyObject * name = NULL ;
348+ PyObject * name = NULL ;
353349
354- // Parse the previous frame using the gi_iframe from local copy
355- uintptr_t prev_frame ;
356- uintptr_t gi_iframe_addr = coro_address + (uintptr_t )unwinder -> debug_offsets .gen_object .gi_iframe ;
357- uintptr_t address_of_code_object = 0 ;
358- if (parse_frame_object (unwinder , & name , gi_iframe_addr , & address_of_code_object , & prev_frame ) < 0 ) {
359- set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to parse frame object in coro chain" );
360- return -1 ;
361- }
350+ // Parse the previous frame using the gi_iframe from local copy
351+ uintptr_t prev_frame ;
352+ uintptr_t gi_iframe_addr = coro_address + (uintptr_t )unwinder -> debug_offsets .gen_object .gi_iframe ;
353+ uintptr_t address_of_code_object = 0 ;
354+ if (parse_frame_object (unwinder , & name , gi_iframe_addr , & address_of_code_object , & prev_frame ) < 0 ) {
355+ set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to parse frame object in coro chain" );
356+ return -1 ;
357+ }
362358
363- if (!name ) {
364- return 0 ;
365- }
359+ if (!name ) {
360+ return 0 ;
361+ }
366362
367- if (PyList_Append (render_to , name )) {
363+ if (PyList_Append (render_to , name )) {
364+ Py_DECREF (name );
365+ set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to append frame to coro chain" );
366+ return -1 ;
367+ }
368368 Py_DECREF (name );
369- set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to append frame to coro chain" );
370- return -1 ;
371- }
372- Py_DECREF (name );
373369
374- if (frame_state == FRAME_SUSPENDED_YIELD_FROM ) {
375- return handle_yield_from_frame (unwinder , gi_iframe_addr , gen_type_addr ,
376- render_to , depth );
370+ if (frame_state != FRAME_SUSPENDED_YIELD_FROM ) {
371+ return 0 ;
372+ }
373+
374+ if (get_awaited_coro_address (unwinder , gi_iframe_addr , gen_type_addr ,
375+ & coro_address ) < 0 ) {
376+ return -1 ;
377+ }
377378 }
378379
379380 return 0 ;
@@ -419,7 +420,7 @@ create_task_result(
419420 coro_addr = GET_MEMBER_NO_TAG (uintptr_t , task_obj , unwinder -> async_debug_offsets .asyncio_task_object .task_coro );
420421
421422 if ((void * )coro_addr != NULL ) {
422- if (parse_coro_chain (unwinder , coro_addr , call_stack , 0 ) < 0 ) {
423+ if (parse_coro_chain (unwinder , coro_addr , call_stack ) < 0 ) {
423424 set_exception_cause (unwinder , PyExc_RuntimeError , "Failed to parse coroutine chain" );
424425 goto error ;
425426 }
0 commit comments