https://github.com/python/cpython/commit/bd2ed7c7ce58084c682ab05d4aaa3a28b774b249
commit: bd2ed7c7ce58084c682ab05d4aaa3a28b774b249
branch: main
author: Sergey Miryanov <[email protected]>
committer: pablogsal <[email protected]>
date: 2025-05-03T01:35:30+02:00
summary:
gh-91048: Chain some exceptions in _testexternalinspection.c (#132970)
files:
M Modules/_testexternalinspection.c
M Python/remote_debug.h
diff --git a/Modules/_testexternalinspection.c
b/Modules/_testexternalinspection.c
index b43e8b2155730f..b65c5821443ebf 100644
--- a/Modules/_testexternalinspection.c
+++ b/Modules/_testexternalinspection.c
@@ -45,6 +45,15 @@ struct _Py_AsyncioModuleDebugOffsets {
} 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
static uintptr_t
_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");
}
#else
- address = 0;
+ Py_UNREACHABLE();
#endif
return address;
@@ -304,7 +313,7 @@ parse_task_name(
if ((flags & Py_TPFLAGS_LONG_SUBCLASS)) {
long res = read_py_long(handle, offsets, task_name_addr);
if (res == -1) {
- PyErr_SetString(PyExc_RuntimeError, "Failed to get task name");
+ chain_exceptions(PyExc_RuntimeError, "Failed to get task name");
return NULL;
}
return PyUnicode_FromFormat("Task-%d", res);
@@ -482,9 +491,6 @@ parse_task(
return -1;
}
- uintptr_t refcnt;
- read_ptr(handle, task_address + sizeof(Py_ssize_t), &refcnt);
-
PyObject* result = PyList_New(0);
if (result == NULL) {
return -1;
@@ -1159,30 +1165,32 @@ get_all_awaited_by(PyObject* self, PyObject* args)
return 0;
}
+ PyObject *result = NULL;
+
uintptr_t runtime_start_addr = _Py_RemoteDebug_GetPyRuntimeAddress(handle);
if (runtime_start_addr == 0) {
if (!PyErr_Occurred()) {
PyErr_SetString(
PyExc_RuntimeError, "Failed to get .PyRuntime address");
}
- return NULL;
+ goto result_err;
}
struct _Py_DebugOffsets local_debug_offsets;
if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_addr,
&local_debug_offsets)) {
- PyErr_SetString(PyExc_RuntimeError, "Failed to read debug offsets");
- return NULL;
+ chain_exceptions(PyExc_RuntimeError, "Failed to read debug offsets");
+ goto result_err;
}
struct _Py_AsyncioModuleDebugOffsets local_async_debug;
if (read_async_debug(handle, &local_async_debug)) {
- PyErr_SetString(PyExc_RuntimeError, "Failed to read asyncio debug
offsets");
- return NULL;
+ chain_exceptions(PyExc_RuntimeError, "Failed to read asyncio debug
offsets");
+ goto result_err;
}
- PyObject *result = PyList_New(0);
+ result = PyList_New(0);
if (result == NULL) {
- return NULL;
+ goto result_err;
}
uint64_t interpreter_state_list_head =
@@ -1259,7 +1267,7 @@ get_all_awaited_by(PyObject* self, PyObject* args)
return result;
result_err:
- Py_DECREF(result);
+ Py_XDECREF(result);
_Py_RemoteDebug_CleanupProcHandle(handle);
return NULL;
}
@@ -1299,7 +1307,7 @@ get_stack_trace(PyObject* self, PyObject* args)
struct _Py_DebugOffsets 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;
}
@@ -1357,40 +1365,40 @@ get_async_stack_trace(PyObject* self, PyObject* args)
return 0;
}
+ PyObject *result = NULL;
+
uintptr_t runtime_start_address =
_Py_RemoteDebug_GetPyRuntimeAddress(handle);
if (runtime_start_address == 0) {
if (!PyErr_Occurred()) {
PyErr_SetString(
PyExc_RuntimeError, "Failed to get .PyRuntime address");
}
- return NULL;
+ goto result_err;
}
struct _Py_DebugOffsets local_debug_offsets;
if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_address,
&local_debug_offsets)) {
- PyErr_SetString(PyExc_RuntimeError, "Failed to read debug offsets");
- return NULL;
+ chain_exceptions(PyExc_RuntimeError, "Failed to read debug offsets");
+ goto result_err;
}
struct _Py_AsyncioModuleDebugOffsets local_async_debug;
if (read_async_debug(handle, &local_async_debug)) {
- PyErr_SetString(PyExc_RuntimeError, "Failed to read asyncio debug
offsets");
- return NULL;
+ chain_exceptions(PyExc_RuntimeError, "Failed to read asyncio debug
offsets");
+ goto result_err;
}
- PyObject* result = PyList_New(1);
+ result = PyList_New(1);
if (result == NULL) {
- return NULL;
+ goto result_err;
}
PyObject* calls = PyList_New(0);
if (calls == NULL) {
- Py_DECREF(result);
- return NULL;
+ goto result_err;
}
if (PyList_SetItem(result, 0, calls)) { /* steals ref to 'calls' */
- Py_DECREF(result);
Py_DECREF(calls);
- return NULL;
+ goto result_err;
}
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,
&running_task_addr)
) {
- PyErr_SetString(PyExc_RuntimeError, "Failed to find running task");
+ chain_exceptions(PyExc_RuntimeError, "Failed to find running task");
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_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;
}
@@ -1443,7 +1451,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
handle, runtime_start_address, &local_debug_offsets,
&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;
}
@@ -1459,7 +1467,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
);
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;
}
@@ -1501,7 +1509,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
result_err:
_Py_RemoteDebug_CleanupProcHandle(handle);
- Py_DECREF(result);
+ Py_XDECREF(result);
return NULL;
}
diff --git a/Python/remote_debug.h b/Python/remote_debug.h
index cb1baf799052d5..edc77c302916ca 100644
--- a/Python/remote_debug.h
+++ b/Python/remote_debug.h
@@ -342,6 +342,7 @@ search_section_in_file(const char* secname, char* path,
uintptr_t base, mach_vm_
munmap(map, fs.st_size);
if (close(fd) != 0) {
PyErr_SetFromErrno(PyExc_OSError);
+ result = 0;
}
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);
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;
}
@@ -495,6 +498,7 @@ search_elf_file_for_section(
}
if (fd >= 0 && close(fd) != 0) {
PyErr_SetFromErrno(PyExc_OSError);
+ result = 0;
}
return result;
}
@@ -570,7 +574,10 @@ search_linux_map_for_section(proc_handle_t *handle, const
char* secname, const c
}
PyMem_Free(line);
- fclose(maps_file);
+ if (fclose(maps_file) != 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ retval = 0;
+ }
return retval;
}
@@ -681,14 +688,18 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle)
address = search_windows_map_for_section(handle, "PyRuntime", L"python");
if (address == 0) {
// 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_ChainExceptions1(exc);
}
#elif defined(__linux__)
// On Linux, search for 'python' in executable or DLL
address = search_linux_map_for_section(handle, "PyRuntime", "python");
if (address == 0) {
// 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_ChainExceptions1(exc);
}
#elif defined(__APPLE__) && TARGET_OS_OSX
// 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");
}
#else
- address = 0;
+ Py_UNREACHABLE();
#endif
return address;
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]