gh-91048: Chain some exceptions in _testexternalinspection.c (#132970)
This commit is contained in:
@@ -45,6 +45,15 @@ struct _Py_AsyncioModuleDebugOffsets {
|
|||||||
} asyncio_thread_state;
|
} asyncio_thread_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper to chain exceptions and avoid repetitions
|
||||||
|
static void
|
||||||
|
chain_exceptions(PyObject *exception, const char *string)
|
||||||
|
{
|
||||||
|
PyObject *exc = PyErr_GetRaisedException();
|
||||||
|
PyErr_SetString(exception, string);
|
||||||
|
_PyErr_ChainExceptions1(exc);
|
||||||
|
}
|
||||||
|
|
||||||
// Get the PyAsyncioDebug section address for any platform
|
// Get the PyAsyncioDebug section address for any platform
|
||||||
static uintptr_t
|
static uintptr_t
|
||||||
_Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle)
|
_Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle)
|
||||||
@@ -65,7 +74,7 @@ _Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle)
|
|||||||
address = search_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython");
|
address = search_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
address = 0;
|
Py_UNREACHABLE();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return address;
|
return address;
|
||||||
@@ -304,7 +313,7 @@ parse_task_name(
|
|||||||
if ((flags & Py_TPFLAGS_LONG_SUBCLASS)) {
|
if ((flags & Py_TPFLAGS_LONG_SUBCLASS)) {
|
||||||
long res = read_py_long(handle, offsets, task_name_addr);
|
long res = read_py_long(handle, offsets, task_name_addr);
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to get task name");
|
chain_exceptions(PyExc_RuntimeError, "Failed to get task name");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return PyUnicode_FromFormat("Task-%d", res);
|
return PyUnicode_FromFormat("Task-%d", res);
|
||||||
@@ -482,9 +491,6 @@ parse_task(
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t refcnt;
|
|
||||||
read_ptr(handle, task_address + sizeof(Py_ssize_t), &refcnt);
|
|
||||||
|
|
||||||
PyObject* result = PyList_New(0);
|
PyObject* result = PyList_New(0);
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1159,30 +1165,32 @@ get_all_awaited_by(PyObject* self, PyObject* args)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *result = NULL;
|
||||||
|
|
||||||
uintptr_t runtime_start_addr = _Py_RemoteDebug_GetPyRuntimeAddress(handle);
|
uintptr_t runtime_start_addr = _Py_RemoteDebug_GetPyRuntimeAddress(handle);
|
||||||
if (runtime_start_addr == 0) {
|
if (runtime_start_addr == 0) {
|
||||||
if (!PyErr_Occurred()) {
|
if (!PyErr_Occurred()) {
|
||||||
PyErr_SetString(
|
PyErr_SetString(
|
||||||
PyExc_RuntimeError, "Failed to get .PyRuntime address");
|
PyExc_RuntimeError, "Failed to get .PyRuntime address");
|
||||||
}
|
}
|
||||||
return NULL;
|
goto result_err;
|
||||||
}
|
}
|
||||||
struct _Py_DebugOffsets local_debug_offsets;
|
struct _Py_DebugOffsets local_debug_offsets;
|
||||||
|
|
||||||
if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_addr, &local_debug_offsets)) {
|
if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_addr, &local_debug_offsets)) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to read debug offsets");
|
chain_exceptions(PyExc_RuntimeError, "Failed to read debug offsets");
|
||||||
return NULL;
|
goto result_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _Py_AsyncioModuleDebugOffsets local_async_debug;
|
struct _Py_AsyncioModuleDebugOffsets local_async_debug;
|
||||||
if (read_async_debug(handle, &local_async_debug)) {
|
if (read_async_debug(handle, &local_async_debug)) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to read asyncio debug offsets");
|
chain_exceptions(PyExc_RuntimeError, "Failed to read asyncio debug offsets");
|
||||||
return NULL;
|
goto result_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *result = PyList_New(0);
|
result = PyList_New(0);
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
return NULL;
|
goto result_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t interpreter_state_list_head =
|
uint64_t interpreter_state_list_head =
|
||||||
@@ -1259,7 +1267,7 @@ get_all_awaited_by(PyObject* self, PyObject* args)
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
result_err:
|
result_err:
|
||||||
Py_DECREF(result);
|
Py_XDECREF(result);
|
||||||
_Py_RemoteDebug_CleanupProcHandle(handle);
|
_Py_RemoteDebug_CleanupProcHandle(handle);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1299,7 +1307,7 @@ get_stack_trace(PyObject* self, PyObject* args)
|
|||||||
struct _Py_DebugOffsets local_debug_offsets;
|
struct _Py_DebugOffsets local_debug_offsets;
|
||||||
|
|
||||||
if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_address, &local_debug_offsets)) {
|
if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_address, &local_debug_offsets)) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to read debug offsets");
|
chain_exceptions(PyExc_RuntimeError, "Failed to read debug offsets");
|
||||||
goto result_err;
|
goto result_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1357,40 +1365,40 @@ get_async_stack_trace(PyObject* self, PyObject* args)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *result = NULL;
|
||||||
|
|
||||||
uintptr_t runtime_start_address = _Py_RemoteDebug_GetPyRuntimeAddress(handle);
|
uintptr_t runtime_start_address = _Py_RemoteDebug_GetPyRuntimeAddress(handle);
|
||||||
if (runtime_start_address == 0) {
|
if (runtime_start_address == 0) {
|
||||||
if (!PyErr_Occurred()) {
|
if (!PyErr_Occurred()) {
|
||||||
PyErr_SetString(
|
PyErr_SetString(
|
||||||
PyExc_RuntimeError, "Failed to get .PyRuntime address");
|
PyExc_RuntimeError, "Failed to get .PyRuntime address");
|
||||||
}
|
}
|
||||||
return NULL;
|
goto result_err;
|
||||||
}
|
}
|
||||||
struct _Py_DebugOffsets local_debug_offsets;
|
struct _Py_DebugOffsets local_debug_offsets;
|
||||||
|
|
||||||
if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_address, &local_debug_offsets)) {
|
if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_address, &local_debug_offsets)) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to read debug offsets");
|
chain_exceptions(PyExc_RuntimeError, "Failed to read debug offsets");
|
||||||
return NULL;
|
goto result_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _Py_AsyncioModuleDebugOffsets local_async_debug;
|
struct _Py_AsyncioModuleDebugOffsets local_async_debug;
|
||||||
if (read_async_debug(handle, &local_async_debug)) {
|
if (read_async_debug(handle, &local_async_debug)) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to read asyncio debug offsets");
|
chain_exceptions(PyExc_RuntimeError, "Failed to read asyncio debug offsets");
|
||||||
return NULL;
|
goto result_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* result = PyList_New(1);
|
result = PyList_New(1);
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
return NULL;
|
goto result_err;
|
||||||
}
|
}
|
||||||
PyObject* calls = PyList_New(0);
|
PyObject* calls = PyList_New(0);
|
||||||
if (calls == NULL) {
|
if (calls == NULL) {
|
||||||
Py_DECREF(result);
|
goto result_err;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
if (PyList_SetItem(result, 0, calls)) { /* steals ref to 'calls' */
|
if (PyList_SetItem(result, 0, calls)) { /* steals ref to 'calls' */
|
||||||
Py_DECREF(result);
|
|
||||||
Py_DECREF(calls);
|
Py_DECREF(calls);
|
||||||
return NULL;
|
goto result_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t running_task_addr = (uintptr_t)NULL;
|
uintptr_t running_task_addr = (uintptr_t)NULL;
|
||||||
@@ -1398,7 +1406,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
|
|||||||
handle, runtime_start_address, &local_debug_offsets, &local_async_debug,
|
handle, runtime_start_address, &local_debug_offsets, &local_async_debug,
|
||||||
&running_task_addr)
|
&running_task_addr)
|
||||||
) {
|
) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to find running task");
|
chain_exceptions(PyExc_RuntimeError, "Failed to find running task");
|
||||||
goto result_err;
|
goto result_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1413,7 +1421,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
|
|||||||
running_task_addr + local_async_debug.asyncio_task_object.task_coro,
|
running_task_addr + local_async_debug.asyncio_task_object.task_coro,
|
||||||
&running_coro_addr
|
&running_coro_addr
|
||||||
)) {
|
)) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to read running task coro");
|
chain_exceptions(PyExc_RuntimeError, "Failed to read running task coro");
|
||||||
goto result_err;
|
goto result_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1443,7 +1451,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
|
|||||||
handle, runtime_start_address, &local_debug_offsets,
|
handle, runtime_start_address, &local_debug_offsets,
|
||||||
&address_of_current_frame)
|
&address_of_current_frame)
|
||||||
) {
|
) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to find running frame");
|
chain_exceptions(PyExc_RuntimeError, "Failed to find running frame");
|
||||||
goto result_err;
|
goto result_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1459,7 +1467,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to parse async frame object");
|
chain_exceptions(PyExc_RuntimeError, "Failed to parse async frame object");
|
||||||
goto result_err;
|
goto result_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1501,7 +1509,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
|
|||||||
|
|
||||||
result_err:
|
result_err:
|
||||||
_Py_RemoteDebug_CleanupProcHandle(handle);
|
_Py_RemoteDebug_CleanupProcHandle(handle);
|
||||||
Py_DECREF(result);
|
Py_XDECREF(result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -342,6 +342,7 @@ search_section_in_file(const char* secname, char* path, uintptr_t base, mach_vm_
|
|||||||
munmap(map, fs.st_size);
|
munmap(map, fs.st_size);
|
||||||
if (close(fd) != 0) {
|
if (close(fd) != 0) {
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
result = 0;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -371,7 +372,9 @@ search_map_for_section(proc_handle_t *handle, const char* secname, const char* s
|
|||||||
|
|
||||||
mach_port_t proc_ref = pid_to_task(handle->pid);
|
mach_port_t proc_ref = pid_to_task(handle->pid);
|
||||||
if (proc_ref == 0) {
|
if (proc_ref == 0) {
|
||||||
PyErr_SetString(PyExc_PermissionError, "Cannot get task for PID");
|
if (!PyErr_Occurred()) {
|
||||||
|
PyErr_SetString(PyExc_PermissionError, "Cannot get task for PID");
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,6 +498,7 @@ exit:
|
|||||||
}
|
}
|
||||||
if (fd >= 0 && close(fd) != 0) {
|
if (fd >= 0 && close(fd) != 0) {
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
result = 0;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -570,7 +574,10 @@ search_linux_map_for_section(proc_handle_t *handle, const char* secname, const c
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyMem_Free(line);
|
PyMem_Free(line);
|
||||||
fclose(maps_file);
|
if (fclose(maps_file) != 0) {
|
||||||
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
retval = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@@ -681,14 +688,18 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle)
|
|||||||
address = search_windows_map_for_section(handle, "PyRuntime", L"python");
|
address = search_windows_map_for_section(handle, "PyRuntime", L"python");
|
||||||
if (address == 0) {
|
if (address == 0) {
|
||||||
// Error out: 'python' substring covers both executable and DLL
|
// Error out: 'python' substring covers both executable and DLL
|
||||||
|
PyObject *exc = PyErr_GetRaisedException();
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to find the PyRuntime section in the process.");
|
PyErr_SetString(PyExc_RuntimeError, "Failed to find the PyRuntime section in the process.");
|
||||||
|
_PyErr_ChainExceptions1(exc);
|
||||||
}
|
}
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
// On Linux, search for 'python' in executable or DLL
|
// On Linux, search for 'python' in executable or DLL
|
||||||
address = search_linux_map_for_section(handle, "PyRuntime", "python");
|
address = search_linux_map_for_section(handle, "PyRuntime", "python");
|
||||||
if (address == 0) {
|
if (address == 0) {
|
||||||
// Error out: 'python' substring covers both executable and DLL
|
// Error out: 'python' substring covers both executable and DLL
|
||||||
|
PyObject *exc = PyErr_GetRaisedException();
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Failed to find the PyRuntime section in the process.");
|
PyErr_SetString(PyExc_RuntimeError, "Failed to find the PyRuntime section in the process.");
|
||||||
|
_PyErr_ChainExceptions1(exc);
|
||||||
}
|
}
|
||||||
#elif defined(__APPLE__) && TARGET_OS_OSX
|
#elif defined(__APPLE__) && TARGET_OS_OSX
|
||||||
// On macOS, try libpython first, then fall back to python
|
// On macOS, try libpython first, then fall back to python
|
||||||
@@ -699,7 +710,7 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle)
|
|||||||
address = search_map_for_section(handle, "PyRuntime", "python");
|
address = search_map_for_section(handle, "PyRuntime", "python");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
address = 0;
|
Py_UNREACHABLE();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return address;
|
return address;
|
||||||
|
|||||||
Reference in New Issue
Block a user