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

Reply via email to