Skip to content

Commit bd2ed7c

Browse files
gh-91048: Chain some exceptions in _testexternalinspection.c (#132970)
1 parent 49ea8a0 commit bd2ed7c

File tree

2 files changed

+52
-33
lines changed

2 files changed

+52
-33
lines changed

Modules/_testexternalinspection.c

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ struct _Py_AsyncioModuleDebugOffsets {
4545
} asyncio_thread_state;
4646
};
4747

48+
// Helper to chain exceptions and avoid repetitions
49+
static void
50+
chain_exceptions(PyObject *exception, const char *string)
51+
{
52+
PyObject *exc = PyErr_GetRaisedException();
53+
PyErr_SetString(exception, string);
54+
_PyErr_ChainExceptions1(exc);
55+
}
56+
4857
// Get the PyAsyncioDebug section address for any platform
4958
static uintptr_t
5059
_Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle)
@@ -65,7 +74,7 @@ _Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle)
6574
address = search_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython");
6675
}
6776
#else
68-
address = 0;
77+
Py_UNREACHABLE();
6978
#endif
7079

7180
return address;
@@ -304,7 +313,7 @@ parse_task_name(
304313
if ((flags & Py_TPFLAGS_LONG_SUBCLASS)) {
305314
long res = read_py_long(handle, offsets, task_name_addr);
306315
if (res == -1) {
307-
PyErr_SetString(PyExc_RuntimeError, "Failed to get task name");
316+
chain_exceptions(PyExc_RuntimeError, "Failed to get task name");
308317
return NULL;
309318
}
310319
return PyUnicode_FromFormat("Task-%d", res);
@@ -482,9 +491,6 @@ parse_task(
482491
return -1;
483492
}
484493

485-
uintptr_t refcnt;
486-
read_ptr(handle, task_address + sizeof(Py_ssize_t), &refcnt);
487-
488494
PyObject* result = PyList_New(0);
489495
if (result == NULL) {
490496
return -1;
@@ -1159,30 +1165,32 @@ get_all_awaited_by(PyObject* self, PyObject* args)
11591165
return 0;
11601166
}
11611167

1168+
PyObject *result = NULL;
1169+
11621170
uintptr_t runtime_start_addr = _Py_RemoteDebug_GetPyRuntimeAddress(handle);
11631171
if (runtime_start_addr == 0) {
11641172
if (!PyErr_Occurred()) {
11651173
PyErr_SetString(
11661174
PyExc_RuntimeError, "Failed to get .PyRuntime address");
11671175
}
1168-
return NULL;
1176+
goto result_err;
11691177
}
11701178
struct _Py_DebugOffsets local_debug_offsets;
11711179

11721180
if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_addr, &local_debug_offsets)) {
1173-
PyErr_SetString(PyExc_RuntimeError, "Failed to read debug offsets");
1174-
return NULL;
1181+
chain_exceptions(PyExc_RuntimeError, "Failed to read debug offsets");
1182+
goto result_err;
11751183
}
11761184

11771185
struct _Py_AsyncioModuleDebugOffsets local_async_debug;
11781186
if (read_async_debug(handle, &local_async_debug)) {
1179-
PyErr_SetString(PyExc_RuntimeError, "Failed to read asyncio debug offsets");
1180-
return NULL;
1187+
chain_exceptions(PyExc_RuntimeError, "Failed to read asyncio debug offsets");
1188+
goto result_err;
11811189
}
11821190

1183-
PyObject *result = PyList_New(0);
1191+
result = PyList_New(0);
11841192
if (result == NULL) {
1185-
return NULL;
1193+
goto result_err;
11861194
}
11871195

11881196
uint64_t interpreter_state_list_head =
@@ -1259,7 +1267,7 @@ get_all_awaited_by(PyObject* self, PyObject* args)
12591267
return result;
12601268

12611269
result_err:
1262-
Py_DECREF(result);
1270+
Py_XDECREF(result);
12631271
_Py_RemoteDebug_CleanupProcHandle(handle);
12641272
return NULL;
12651273
}
@@ -1299,7 +1307,7 @@ get_stack_trace(PyObject* self, PyObject* args)
12991307
struct _Py_DebugOffsets local_debug_offsets;
13001308

13011309
if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_address, &local_debug_offsets)) {
1302-
PyErr_SetString(PyExc_RuntimeError, "Failed to read debug offsets");
1310+
chain_exceptions(PyExc_RuntimeError, "Failed to read debug offsets");
13031311
goto result_err;
13041312
}
13051313

@@ -1357,48 +1365,48 @@ get_async_stack_trace(PyObject* self, PyObject* args)
13571365
return 0;
13581366
}
13591367

1368+
PyObject *result = NULL;
1369+
13601370
uintptr_t runtime_start_address = _Py_RemoteDebug_GetPyRuntimeAddress(handle);
13611371
if (runtime_start_address == 0) {
13621372
if (!PyErr_Occurred()) {
13631373
PyErr_SetString(
13641374
PyExc_RuntimeError, "Failed to get .PyRuntime address");
13651375
}
1366-
return NULL;
1376+
goto result_err;
13671377
}
13681378
struct _Py_DebugOffsets local_debug_offsets;
13691379

13701380
if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_address, &local_debug_offsets)) {
1371-
PyErr_SetString(PyExc_RuntimeError, "Failed to read debug offsets");
1372-
return NULL;
1381+
chain_exceptions(PyExc_RuntimeError, "Failed to read debug offsets");
1382+
goto result_err;
13731383
}
13741384

13751385
struct _Py_AsyncioModuleDebugOffsets local_async_debug;
13761386
if (read_async_debug(handle, &local_async_debug)) {
1377-
PyErr_SetString(PyExc_RuntimeError, "Failed to read asyncio debug offsets");
1378-
return NULL;
1387+
chain_exceptions(PyExc_RuntimeError, "Failed to read asyncio debug offsets");
1388+
goto result_err;
13791389
}
13801390

1381-
PyObject* result = PyList_New(1);
1391+
result = PyList_New(1);
13821392
if (result == NULL) {
1383-
return NULL;
1393+
goto result_err;
13841394
}
13851395
PyObject* calls = PyList_New(0);
13861396
if (calls == NULL) {
1387-
Py_DECREF(result);
1388-
return NULL;
1397+
goto result_err;
13891398
}
13901399
if (PyList_SetItem(result, 0, calls)) { /* steals ref to 'calls' */
1391-
Py_DECREF(result);
13921400
Py_DECREF(calls);
1393-
return NULL;
1401+
goto result_err;
13941402
}
13951403

13961404
uintptr_t running_task_addr = (uintptr_t)NULL;
13971405
if (find_running_task(
13981406
handle, runtime_start_address, &local_debug_offsets, &local_async_debug,
13991407
&running_task_addr)
14001408
) {
1401-
PyErr_SetString(PyExc_RuntimeError, "Failed to find running task");
1409+
chain_exceptions(PyExc_RuntimeError, "Failed to find running task");
14021410
goto result_err;
14031411
}
14041412

@@ -1413,7 +1421,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
14131421
running_task_addr + local_async_debug.asyncio_task_object.task_coro,
14141422
&running_coro_addr
14151423
)) {
1416-
PyErr_SetString(PyExc_RuntimeError, "Failed to read running task coro");
1424+
chain_exceptions(PyExc_RuntimeError, "Failed to read running task coro");
14171425
goto result_err;
14181426
}
14191427

@@ -1443,7 +1451,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
14431451
handle, runtime_start_address, &local_debug_offsets,
14441452
&address_of_current_frame)
14451453
) {
1446-
PyErr_SetString(PyExc_RuntimeError, "Failed to find running frame");
1454+
chain_exceptions(PyExc_RuntimeError, "Failed to find running frame");
14471455
goto result_err;
14481456
}
14491457

@@ -1459,7 +1467,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
14591467
);
14601468

14611469
if (res < 0) {
1462-
PyErr_SetString(PyExc_RuntimeError, "Failed to parse async frame object");
1470+
chain_exceptions(PyExc_RuntimeError, "Failed to parse async frame object");
14631471
goto result_err;
14641472
}
14651473

@@ -1501,7 +1509,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
15011509

15021510
result_err:
15031511
_Py_RemoteDebug_CleanupProcHandle(handle);
1504-
Py_DECREF(result);
1512+
Py_XDECREF(result);
15051513
return NULL;
15061514
}
15071515

Python/remote_debug.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ search_section_in_file(const char* secname, char* path, uintptr_t base, mach_vm_
342342
munmap(map, fs.st_size);
343343
if (close(fd) != 0) {
344344
PyErr_SetFromErrno(PyExc_OSError);
345+
result = 0;
345346
}
346347
return result;
347348
}
@@ -371,7 +372,9 @@ search_map_for_section(proc_handle_t *handle, const char* secname, const char* s
371372

372373
mach_port_t proc_ref = pid_to_task(handle->pid);
373374
if (proc_ref == 0) {
374-
PyErr_SetString(PyExc_PermissionError, "Cannot get task for PID");
375+
if (!PyErr_Occurred()) {
376+
PyErr_SetString(PyExc_PermissionError, "Cannot get task for PID");
377+
}
375378
return 0;
376379
}
377380

@@ -495,6 +498,7 @@ search_elf_file_for_section(
495498
}
496499
if (fd >= 0 && close(fd) != 0) {
497500
PyErr_SetFromErrno(PyExc_OSError);
501+
result = 0;
498502
}
499503
return result;
500504
}
@@ -570,7 +574,10 @@ search_linux_map_for_section(proc_handle_t *handle, const char* secname, const c
570574
}
571575

572576
PyMem_Free(line);
573-
fclose(maps_file);
577+
if (fclose(maps_file) != 0) {
578+
PyErr_SetFromErrno(PyExc_OSError);
579+
retval = 0;
580+
}
574581

575582
return retval;
576583
}
@@ -681,14 +688,18 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle)
681688
address = search_windows_map_for_section(handle, "PyRuntime", L"python");
682689
if (address == 0) {
683690
// Error out: 'python' substring covers both executable and DLL
691+
PyObject *exc = PyErr_GetRaisedException();
684692
PyErr_SetString(PyExc_RuntimeError, "Failed to find the PyRuntime section in the process.");
693+
_PyErr_ChainExceptions1(exc);
685694
}
686695
#elif defined(__linux__)
687696
// On Linux, search for 'python' in executable or DLL
688697
address = search_linux_map_for_section(handle, "PyRuntime", "python");
689698
if (address == 0) {
690699
// Error out: 'python' substring covers both executable and DLL
700+
PyObject *exc = PyErr_GetRaisedException();
691701
PyErr_SetString(PyExc_RuntimeError, "Failed to find the PyRuntime section in the process.");
702+
_PyErr_ChainExceptions1(exc);
692703
}
693704
#elif defined(__APPLE__) && TARGET_OS_OSX
694705
// On macOS, try libpython first, then fall back to python
@@ -699,7 +710,7 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle)
699710
address = search_map_for_section(handle, "PyRuntime", "python");
700711
}
701712
#else
702-
address = 0;
713+
Py_UNREACHABLE();
703714
#endif
704715

705716
return address;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy