Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix compilation problems in ``_remote_debugging_module.c`` when the system
doesn't have ``process_vm_readv``. Patch by Pablo Galindo
133 changes: 132 additions & 1 deletion Modules/_remote_debugging_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ _Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle)
PyErr_SetString(PyExc_RuntimeError, "Failed to find the AsyncioDebug section in the process.");
_PyErr_ChainExceptions1(exc);
}
#elif defined(__linux__)
#elif defined(__linux__) && HAVE_PROCESS_VM_READV
// On Linux, search for asyncio debug in executable or DLL
address = search_linux_map_for_section(handle, "AsyncioDebug", "python");
if (address == 0) {
Expand Down Expand Up @@ -2453,6 +2453,137 @@ process_frame_chain(
return 0;
}

<<<<<<< Updated upstream
=======
static int
get_thread_status(RemoteUnwinderObject *unwinder, uint64_t tid, uint64_t pthread_id) {
#if defined(__APPLE__) && TARGET_OS_OSX
if (unwinder->thread_id_offset == 0) {
uint64_t *tids = (uint64_t *)PyMem_Malloc(MAX_NATIVE_THREADS * sizeof(uint64_t));
if (!tids) {
PyErr_NoMemory();
return -1;
}
int n = proc_pidinfo(unwinder->handle.pid, PROC_PIDLISTTHREADS, 0, tids, MAX_NATIVE_THREADS * sizeof(uint64_t)) / sizeof(uint64_t);
if (n <= 0) {
PyMem_Free(tids);
return THREAD_STATE_UNKNOWN;
}
uint64_t min_offset = UINT64_MAX;
for (int i = 0; i < n; i++) {
uint64_t offset = tids[i] - pthread_id;
if (offset < min_offset) {
min_offset = offset;
}
}
unwinder->thread_id_offset = min_offset;
PyMem_Free(tids);
}
struct proc_threadinfo ti;
uint64_t tid_with_offset = pthread_id + unwinder->thread_id_offset;
if (proc_pidinfo(unwinder->handle.pid, PROC_PIDTHREADINFO, tid_with_offset, &ti, sizeof(ti)) != sizeof(ti)) {
return THREAD_STATE_UNKNOWN;
}
if (ti.pth_run_state == TH_STATE_RUNNING) {
return THREAD_STATE_RUNNING;
}
return THREAD_STATE_IDLE;
#elif defined(__linux__) && HAVE_PROCESS_VM_READV
char stat_path[256];
char buffer[2048] = "";

snprintf(stat_path, sizeof(stat_path), "/proc/%d/task/%lu/stat", unwinder->handle.pid, tid);

int fd = open(stat_path, O_RDONLY);
if (fd == -1) {
return THREAD_STATE_UNKNOWN;
}

if (read(fd, buffer, 2047) == 0) {
close(fd);
return THREAD_STATE_UNKNOWN;
}
close(fd);

char *p = strchr(buffer, ')');
if (!p) {
return THREAD_STATE_UNKNOWN;
}

p += 2; // Skip ") "
if (*p == ' ') {
p++;
}

switch (*p) {
case 'R': // Running
return THREAD_STATE_RUNNING;
case 'S': // Interruptible sleep
case 'D': // Uninterruptible sleep
case 'T': // Stopped
case 'Z': // Zombie
case 'I': // Idle kernel thread
return THREAD_STATE_IDLE;
default:
return THREAD_STATE_UNKNOWN;
}
#elif defined(MS_WINDOWS)
ULONG n;
NTSTATUS status = NtQuerySystemInformation(
SystemProcessInformation,
unwinder->win_process_buffer,
unwinder->win_process_buffer_size,
&n
);
if (status == STATUS_INFO_LENGTH_MISMATCH) {
// Buffer was too small so we reallocate a larger one and try again.
unwinder->win_process_buffer_size = n;
PVOID new_buffer = PyMem_Realloc(unwinder->win_process_buffer, n);
if (!new_buffer) {
return -1;
}
unwinder->win_process_buffer = new_buffer;
return get_thread_status(unwinder, tid, pthread_id);
}
if (status != STATUS_SUCCESS) {
return -1;
}

SYSTEM_PROCESS_INFORMATION *pi = (SYSTEM_PROCESS_INFORMATION *)unwinder->win_process_buffer;
while ((ULONG)(ULONG_PTR)pi->UniqueProcessId != unwinder->handle.pid) {
if (pi->NextEntryOffset == 0) {
// We didn't find the process
return -1;
}
pi = (SYSTEM_PROCESS_INFORMATION *)(((BYTE *)pi) + pi->NextEntryOffset);
}

SYSTEM_THREAD_INFORMATION *ti = (SYSTEM_THREAD_INFORMATION *)((char *)pi + sizeof(SYSTEM_PROCESS_INFORMATION));
for (Py_ssize_t i = 0; i < pi->NumberOfThreads; i++, ti++) {
if (ti->ClientId.UniqueThread == (HANDLE)tid) {
return ti->ThreadState != WIN32_THREADSTATE_RUNNING ? THREAD_STATE_IDLE : THREAD_STATE_RUNNING;
}
}

return -1;
#else
return THREAD_STATE_UNKNOWN;
#endif
}

typedef struct {
unsigned int initialized:1;
unsigned int bound:1;
unsigned int unbound:1;
unsigned int bound_gilstate:1;
unsigned int active:1;
unsigned int finalizing:1;
unsigned int cleared:1;
unsigned int finalized:1;
unsigned int :24;
} _thread_status;

>>>>>>> Stashed changes
static PyObject*
unwind_stack_for_thread(
RemoteUnwinderObject *unwinder,
Expand Down
2 changes: 1 addition & 1 deletion Python/remote_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle)
handle->pid);
_PyErr_ChainExceptions1(exc);
}
#elif defined(__linux__)
#elif defined(__linux__) && HAVE_PROCESS_VM_READV
// On Linux, search for 'python' in executable or DLL
address = search_linux_map_for_section(handle, "PyRuntime", "python");
if (address == 0) {
Expand Down