https://github.com/python/cpython/commit/bd2ed7c7ce58084c682ab05d4aaa3a28b774b249 commit: bd2ed7c7ce58084c682ab05d4aaa3a28b774b249 branch: main author: Sergey Miryanov <sergey.mirya...@gmail.com> committer: pablogsal <pablog...@gmail.com> 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 -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com