@@ -958,7 +958,9 @@ _remote_debugging_RemoteUnwinder_get_all_awaited_by_impl(RemoteUnwinderObject *s
958958 if (ensure_async_debug_offsets (self ) < 0 ) {
959959 return NULL ;
960960 }
961- if (refresh_generation_caches_for_interpreter (self , self -> interpreter_addr ) < 0 ) {
961+ PyObject * seen = PySet_New (NULL );
962+ if (seen == NULL ) {
963+ set_exception_cause (self , PyExc_MemoryError , "Failed to create interpreter set" );
962964 return NULL ;
963965 }
964966
@@ -968,30 +970,65 @@ _remote_debugging_RemoteUnwinder_get_all_awaited_by_impl(RemoteUnwinderObject *s
968970 goto result_err ;
969971 }
970972
971- // Process all threads
972- if (iterate_threads (self , process_thread_for_awaited_by , result ) < 0 ) {
973- goto result_err ;
974- }
973+ // gh-158880: Tasks live in every interpreter, not only the one at the list head
974+ for (uintptr_t interp = self -> interpreter_addr ; interp != 0 ; ) {
975+ PyObject * addr = PyLong_FromUnsignedLongLong (interp );
976+ if (addr == NULL ) {
977+ set_exception_cause (self , PyExc_MemoryError , "Failed to create interpreter address" );
978+ goto result_err ;
979+ }
980+ Py_ssize_t seen_count = PySet_GET_SIZE (seen );
981+ int marked = PySet_Add (seen , addr );
982+ Py_DECREF (addr );
983+ if (marked < 0 ) {
984+ set_exception_cause (self , PyExc_RuntimeError , "Failed to mark interpreter as seen" );
985+ goto result_err ;
986+ }
987+ if (PySet_GET_SIZE (seen ) == seen_count ) {
988+ // already walked
989+ break ;
990+ }
975991
976- uintptr_t head_addr = self -> interpreter_addr
977- + (uintptr_t )self -> async_debug_offsets .asyncio_interpreter_state .asyncio_tasks_head ;
992+ if (refresh_generation_caches_for_interpreter (self , interp ) < 0 ) {
993+ goto result_err ;
994+ }
978995
979- // On top of a per-thread task lists used by default by asyncio to avoid
980- // contention, there is also a fallback per-interpreter list of tasks;
981- // any tasks still pending when a thread is destroyed will be moved to the
982- // per-interpreter task list. It's unlikely we'll find anything here, but
983- // interesting for debugging.
984- if (append_awaited_by (self , 0 , head_addr , result ))
985- {
986- set_exception_cause (self , PyExc_RuntimeError , "Failed to append interpreter awaited_by in get_all_awaited_by" );
987- goto result_err ;
996+ // Process all threads
997+ if (iterate_threads (self , interp , process_thread_for_awaited_by , result ) < 0 ) {
998+ goto result_err ;
999+ }
1000+
1001+ uintptr_t head_addr = interp
1002+ + (uintptr_t )self -> async_debug_offsets .asyncio_interpreter_state .asyncio_tasks_head ;
1003+
1004+ // On top of a per-thread task lists used by default by asyncio to avoid
1005+ // contention, there is also a fallback per-interpreter list of tasks;
1006+ // any tasks still pending when a thread is destroyed will be moved to
1007+ // the per-interpreter task list. It's unlikely we'll find anything
1008+ // here, but interesting for debugging.
1009+ if (append_awaited_by (self , 0 , head_addr , result ))
1010+ {
1011+ set_exception_cause (self , PyExc_RuntimeError , "Failed to append interpreter awaited_by in get_all_awaited_by" );
1012+ goto result_err ;
1013+ }
1014+
1015+ if (_Py_RemoteDebug_PagedReadRemoteMemory (
1016+ & self -> handle ,
1017+ interp + (uintptr_t )self -> debug_offsets .interpreter_state .next ,
1018+ sizeof (void * ),
1019+ & interp ) < 0 ) {
1020+ set_exception_cause (self , PyExc_RuntimeError , "Failed to read next interpreter address" );
1021+ goto result_err ;
1022+ }
9881023 }
9891024
9901025 _Py_RemoteDebug_ClearCache (& self -> handle );
1026+ Py_DECREF (seen );
9911027 return result ;
9921028
9931029result_err :
9941030 _Py_RemoteDebug_ClearCache (& self -> handle );
1031+ Py_DECREF (seen );
9951032 Py_XDECREF (result );
9961033 return NULL ;
9971034}
@@ -1064,7 +1101,8 @@ _remote_debugging_RemoteUnwinder_get_async_stack_trace_impl(RemoteUnwinderObject
10641101 }
10651102
10661103 // Process all threads
1067- if (iterate_threads (self , process_thread_for_async_stack_trace , result ) < 0 ) {
1104+ if (iterate_threads (self , self -> interpreter_addr ,
1105+ process_thread_for_async_stack_trace , result ) < 0 ) {
10681106 goto result_err ;
10691107 }
10701108
0 commit comments