@@ -824,7 +824,7 @@ _Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle)
824824 PyErr_SetString (PyExc_RuntimeError , "Failed to find the AsyncioDebug section in the process." );
825825 _PyErr_ChainExceptions1 (exc );
826826 }
827- #elif defined(__linux__ )
827+ #elif defined(__linux__ ) && HAVE_PROCESS_VM_READV
828828 // On Linux, search for asyncio debug in executable or DLL
829829 address = search_linux_map_for_section (handle , "AsyncioDebug" , "python" );
830830 if (address == 0 ) {
@@ -2453,6 +2453,137 @@ process_frame_chain(
24532453 return 0 ;
24542454}
24552455
2456+ <<<<<<< Updated upstream
2457+ == == == =
2458+ static int
2459+ get_thread_status (RemoteUnwinderObject * unwinder , uint64_t tid , uint64_t pthread_id ) {
2460+ #if defined(__APPLE__ ) && TARGET_OS_OSX
2461+ if (unwinder -> thread_id_offset == 0 ) {
2462+ uint64_t * tids = (uint64_t * )PyMem_Malloc (MAX_NATIVE_THREADS * sizeof (uint64_t ));
2463+ if (!tids ) {
2464+ PyErr_NoMemory ();
2465+ return -1 ;
2466+ }
2467+ int n = proc_pidinfo (unwinder -> handle .pid , PROC_PIDLISTTHREADS , 0 , tids , MAX_NATIVE_THREADS * sizeof (uint64_t )) / sizeof (uint64_t );
2468+ if (n <= 0 ) {
2469+ PyMem_Free (tids );
2470+ return THREAD_STATE_UNKNOWN ;
2471+ }
2472+ uint64_t min_offset = UINT64_MAX ;
2473+ for (int i = 0 ; i < n ; i ++ ) {
2474+ uint64_t offset = tids [i ] - pthread_id ;
2475+ if (offset < min_offset ) {
2476+ min_offset = offset ;
2477+ }
2478+ }
2479+ unwinder -> thread_id_offset = min_offset ;
2480+ PyMem_Free (tids );
2481+ }
2482+ struct proc_threadinfo ti ;
2483+ uint64_t tid_with_offset = pthread_id + unwinder -> thread_id_offset ;
2484+ if (proc_pidinfo (unwinder -> handle .pid , PROC_PIDTHREADINFO , tid_with_offset , & ti , sizeof (ti )) != sizeof (ti )) {
2485+ return THREAD_STATE_UNKNOWN ;
2486+ }
2487+ if (ti .pth_run_state == TH_STATE_RUNNING ) {
2488+ return THREAD_STATE_RUNNING ;
2489+ }
2490+ return THREAD_STATE_IDLE ;
2491+ #elif defined(__linux__ ) && HAVE_PROCESS_VM_READV
2492+ char stat_path [256 ];
2493+ char buffer [2048 ] = "" ;
2494+
2495+ snprintf (stat_path , sizeof (stat_path ), "/proc/%d/task/%lu/stat" , unwinder -> handle .pid , tid );
2496+
2497+ int fd = open (stat_path , O_RDONLY );
2498+ if (fd == -1 ) {
2499+ return THREAD_STATE_UNKNOWN ;
2500+ }
2501+
2502+ if (read (fd , buffer , 2047 ) == 0 ) {
2503+ close (fd );
2504+ return THREAD_STATE_UNKNOWN ;
2505+ }
2506+ close (fd );
2507+
2508+ char * p = strchr (buffer , ')' );
2509+ if (!p ) {
2510+ return THREAD_STATE_UNKNOWN ;
2511+ }
2512+
2513+ p += 2 ; // Skip ") "
2514+ if (* p == ' ' ) {
2515+ p ++ ;
2516+ }
2517+
2518+ switch (* p ) {
2519+ case 'R' : // Running
2520+ return THREAD_STATE_RUNNING ;
2521+ case 'S' : // Interruptible sleep
2522+ case 'D' : // Uninterruptible sleep
2523+ case 'T' : // Stopped
2524+ case 'Z' : // Zombie
2525+ case 'I' : // Idle kernel thread
2526+ return THREAD_STATE_IDLE ;
2527+ default :
2528+ return THREAD_STATE_UNKNOWN ;
2529+ }
2530+ #elif defined(MS_WINDOWS )
2531+ ULONG n ;
2532+ NTSTATUS status = NtQuerySystemInformation (
2533+ SystemProcessInformation ,
2534+ unwinder -> win_process_buffer ,
2535+ unwinder -> win_process_buffer_size ,
2536+ & n
2537+ );
2538+ if (status == STATUS_INFO_LENGTH_MISMATCH ) {
2539+ // Buffer was too small so we reallocate a larger one and try again.
2540+ unwinder -> win_process_buffer_size = n ;
2541+ PVOID new_buffer = PyMem_Realloc (unwinder -> win_process_buffer , n );
2542+ if (!new_buffer ) {
2543+ return -1 ;
2544+ }
2545+ unwinder -> win_process_buffer = new_buffer ;
2546+ return get_thread_status (unwinder , tid , pthread_id );
2547+ }
2548+ if (status != STATUS_SUCCESS ) {
2549+ return -1 ;
2550+ }
2551+
2552+ SYSTEM_PROCESS_INFORMATION * pi = (SYSTEM_PROCESS_INFORMATION * )unwinder -> win_process_buffer ;
2553+ while ((ULONG )(ULONG_PTR )pi -> UniqueProcessId != unwinder -> handle .pid ) {
2554+ if (pi -> NextEntryOffset == 0 ) {
2555+ // We didn't find the process
2556+ return -1 ;
2557+ }
2558+ pi = (SYSTEM_PROCESS_INFORMATION * )(((BYTE * )pi ) + pi -> NextEntryOffset );
2559+ }
2560+
2561+ SYSTEM_THREAD_INFORMATION * ti = (SYSTEM_THREAD_INFORMATION * )((char * )pi + sizeof (SYSTEM_PROCESS_INFORMATION ));
2562+ for (Py_ssize_t i = 0 ; i < pi -> NumberOfThreads ; i ++ , ti ++ ) {
2563+ if (ti -> ClientId .UniqueThread == (HANDLE )tid ) {
2564+ return ti -> ThreadState != WIN32_THREADSTATE_RUNNING ? THREAD_STATE_IDLE : THREAD_STATE_RUNNING ;
2565+ }
2566+ }
2567+
2568+ return -1 ;
2569+ #else
2570+ return THREAD_STATE_UNKNOWN ;
2571+ #endif
2572+ }
2573+
2574+ typedef struct {
2575+ unsigned int initialized :1 ;
2576+ unsigned int bound :1 ;
2577+ unsigned int unbound :1 ;
2578+ unsigned int bound_gilstate :1 ;
2579+ unsigned int active :1 ;
2580+ unsigned int finalizing :1 ;
2581+ unsigned int cleared :1 ;
2582+ unsigned int finalized :1 ;
2583+ unsigned int :24 ;
2584+ } _thread_status ;
2585+
2586+ >>>>>>> Stashed changes
24562587static PyObject *
24572588unwind_stack_for_thread (
24582589 RemoteUnwinderObject * unwinder ,
0 commit comments