Skip to content

Commit b1b6e10

Browse files
committed
pythonGH-91048: Add utils for printing the call stack for asyncio tasks
1 parent b8633f9 commit b1b6e10

12 files changed

+99
-71
lines changed

Lib/test/test_external_inspection.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
PROCESS_VM_READV_SUPPORTED = False
1414

1515
try:
16-
from _testexternalinspection import PROCESS_VM_READV_SUPPORTED
17-
from _testexternalinspection import get_stack_trace
18-
from _testexternalinspection import get_async_stack_trace
19-
from _testexternalinspection import get_all_awaited_by
16+
from _remotedebuggingg import PROCESS_VM_READV_SUPPORTED
17+
from _remotedebuggingg import get_stack_trace
18+
from _remotedebuggingg import get_async_stack_trace
19+
from _remotedebuggingg import get_all_awaited_by
2020
except ImportError:
2121
raise unittest.SkipTest(
22-
"Test only runs when _testexternalinspection is available")
22+
"Test only runs when _remotedebuggingmodule is available")
2323

2424
def _make_test_script(script_dir, script_basename, source):
2525
to_return = make_script(script_dir, script_basename, source)

Lib/test/test_sys.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1960,7 +1960,7 @@ def _supports_remote_attaching():
19601960
PROCESS_VM_READV_SUPPORTED = False
19611961

19621962
try:
1963-
from _testexternalinspection import PROCESS_VM_READV_SUPPORTED
1963+
from _remotedebuggingmodule import PROCESS_VM_READV_SUPPORTED
19641964
except ImportError:
19651965
pass
19661966

Modules/Setup

+1-1
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ PYTHONPATH=$(COREPYTHONPATH)
286286
#_testcapi _testcapimodule.c
287287
#_testimportmultiple _testimportmultiple.c
288288
#_testmultiphase _testmultiphase.c
289-
#_testexternalinspection _testexternalinspection.c
289+
#_remotedebuggingmodule _remotedebuggingmodule.c
290290
#_testsinglephase _testsinglephase.c
291291

292292
# ---

Modules/Setup.stdlib.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
# Modules that should always be present (POSIX and Windows):
3434
@MODULE_ARRAY_TRUE@array arraymodule.c
3535
@MODULE__ASYNCIO_TRUE@_asyncio _asynciomodule.c
36+
@MODULE__REMOTEDEBUGGING_TRUE@_remotedebugging _remotedebuggingmodule.c
3637
@MODULE__BISECT_TRUE@_bisect _bisectmodule.c
3738
@MODULE__CSV_TRUE@_csv _csv.c
3839
@MODULE__HEAPQ_TRUE@_heapq _heapqmodule.c
@@ -186,7 +187,6 @@
186187
@MODULE__TESTIMPORTMULTIPLE_TRUE@_testimportmultiple _testimportmultiple.c
187188
@MODULE__TESTMULTIPHASE_TRUE@_testmultiphase _testmultiphase.c
188189
@MODULE__TESTSINGLEPHASE_TRUE@_testsinglephase _testsinglephase.c
189-
@MODULE__TESTEXTERNALINSPECTION_TRUE@_testexternalinspection _testexternalinspection.c
190190
@MODULE__CTYPES_TEST_TRUE@_ctypes_test _ctypes/_ctypes_test.c
191191

192192
# Limited API template modules; must be built as shared modules.

Modules/_testexternalinspection.c renamed to Modules/_remotedebuggingmodule.c

+62-34
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,9 @@ read_char(proc_handle_t *handle, uintptr_t address, char *result)
143143
}
144144

145145
static int
146-
read_int(proc_handle_t *handle, uintptr_t address, int *result)
146+
read_sized_int(proc_handle_t *handle, uintptr_t address, void *result, size_t size)
147147
{
148-
int res = _Py_RemoteDebug_ReadRemoteMemory(handle, address, sizeof(int), result);
148+
int res = _Py_RemoteDebug_ReadRemoteMemory(handle, address, size, result);
149149
if (res < 0) {
150150
return -1;
151151
}
@@ -367,11 +367,13 @@ parse_coro_chain(
367367
}
368368
Py_DECREF(name);
369369

370-
int gi_frame_state;
371-
err = read_int(
370+
int8_t gi_frame_state;
371+
err = read_sized_int(
372372
handle,
373373
coro_address + offsets->gen_object.gi_frame_state,
374-
&gi_frame_state);
374+
&gi_frame_state,
375+
sizeof(int8_t)
376+
);
375377
if (err) {
376378
return -1;
377379
}
@@ -461,7 +463,8 @@ parse_task_awaited_by(
461463
struct _Py_DebugOffsets* offsets,
462464
struct _Py_AsyncioModuleDebugOffsets* async_offsets,
463465
uintptr_t task_address,
464-
PyObject *awaited_by
466+
PyObject *awaited_by,
467+
int recurse_task
465468
);
466469

467470

@@ -471,7 +474,8 @@ parse_task(
471474
struct _Py_DebugOffsets* offsets,
472475
struct _Py_AsyncioModuleDebugOffsets* async_offsets,
473476
uintptr_t task_address,
474-
PyObject *render_to
477+
PyObject *render_to,
478+
int recurse_task
475479
) {
476480
char is_task;
477481
int err = read_char(
@@ -502,8 +506,13 @@ parse_task(
502506
Py_DECREF(call_stack);
503507

504508
if (is_task) {
505-
PyObject *tn = parse_task_name(
506-
handle, offsets, async_offsets, task_address);
509+
PyObject *tn = NULL;
510+
if (recurse_task) {
511+
tn = parse_task_name(
512+
handle, offsets, async_offsets, task_address);
513+
} else {
514+
tn = PyLong_FromUnsignedLong(task_address);
515+
}
507516
if (tn == NULL) {
508517
goto err;
509518
}
@@ -544,21 +553,23 @@ parse_task(
544553
goto err;
545554
}
546555

547-
PyObject *awaited_by = PyList_New(0);
548-
if (awaited_by == NULL) {
549-
goto err;
550-
}
551-
if (PyList_Append(result, awaited_by)) {
556+
if (recurse_task) {
557+
PyObject *awaited_by = PyList_New(0);
558+
if (awaited_by == NULL) {
559+
goto err;
560+
}
561+
if (PyList_Append(result, awaited_by)) {
562+
Py_DECREF(awaited_by);
563+
goto err;
564+
}
565+
/* we can operate on a borrowed one to simplify cleanup */
552566
Py_DECREF(awaited_by);
553-
goto err;
554-
}
555-
/* we can operate on a borrowed one to simplify cleanup */
556-
Py_DECREF(awaited_by);
557567

558-
if (parse_task_awaited_by(handle, offsets, async_offsets,
559-
task_address, awaited_by)
560-
) {
561-
goto err;
568+
if (parse_task_awaited_by(handle, offsets, async_offsets,
569+
task_address, awaited_by, 1)
570+
) {
571+
goto err;
572+
}
562573
}
563574
Py_DECREF(result);
564575

@@ -575,7 +586,8 @@ parse_tasks_in_set(
575586
struct _Py_DebugOffsets* offsets,
576587
struct _Py_AsyncioModuleDebugOffsets* async_offsets,
577588
uintptr_t set_addr,
578-
PyObject *awaited_by
589+
PyObject *awaited_by,
590+
int recurse_task
579591
) {
580592
uintptr_t set_obj;
581593
if (read_py_ptr(
@@ -636,7 +648,9 @@ parse_tasks_in_set(
636648
offsets,
637649
async_offsets,
638650
key_addr,
639-
awaited_by)
651+
awaited_by,
652+
recurse_task
653+
)
640654
) {
641655
return -1;
642656
}
@@ -660,7 +674,8 @@ parse_task_awaited_by(
660674
struct _Py_DebugOffsets* offsets,
661675
struct _Py_AsyncioModuleDebugOffsets* async_offsets,
662676
uintptr_t task_address,
663-
PyObject *awaited_by
677+
PyObject *awaited_by,
678+
int recurse_task
664679
) {
665680
uintptr_t task_ab_addr;
666681
int err = read_py_ptr(
@@ -690,7 +705,9 @@ parse_task_awaited_by(
690705
offsets,
691706
async_offsets,
692707
task_address + async_offsets->asyncio_task_object.task_awaited_by,
693-
awaited_by)
708+
awaited_by,
709+
recurse_task
710+
)
694711
) {
695712
return -1;
696713
}
@@ -709,7 +726,9 @@ parse_task_awaited_by(
709726
offsets,
710727
async_offsets,
711728
sub_task,
712-
awaited_by)
729+
awaited_by,
730+
recurse_task
731+
)
713732
) {
714733
return -1;
715734
}
@@ -1054,23 +1073,32 @@ append_awaited_by_for_thread(
10541073
return -1;
10551074
}
10561075

1057-
PyObject *result_item = PyTuple_New(2);
1076+
PyObject* task_id = PyLong_FromUnsignedLong(task_addr);
1077+
if (task_id == NULL) {
1078+
Py_DECREF(tn);
1079+
Py_DECREF(current_awaited_by);
1080+
return -1;
1081+
}
1082+
1083+
PyObject *result_item = PyTuple_New(3);
10581084
if (result_item == NULL) {
10591085
Py_DECREF(tn);
10601086
Py_DECREF(current_awaited_by);
1087+
Py_DECREF(task_id);
10611088
return -1;
10621089
}
10631090

1064-
PyTuple_SET_ITEM(result_item, 0, tn); // steals ref
1065-
PyTuple_SET_ITEM(result_item, 1, current_awaited_by); // steals ref
1091+
PyTuple_SET_ITEM(result_item, 0, task_id); // steals ref
1092+
PyTuple_SET_ITEM(result_item, 1, tn); // steals ref
1093+
PyTuple_SET_ITEM(result_item, 2, current_awaited_by); // steals ref
10661094
if (PyList_Append(result, result_item)) {
10671095
Py_DECREF(result_item);
10681096
return -1;
10691097
}
10701098
Py_DECREF(result_item);
10711099

10721100
if (parse_task_awaited_by(handle, debug_offsets, async_offsets,
1073-
task_addr, current_awaited_by))
1101+
task_addr, current_awaited_by, 0))
10741102
{
10751103
return -1;
10761104
}
@@ -1491,7 +1519,7 @@ get_async_stack_trace(PyObject* self, PyObject* args)
14911519

14921520
if (parse_task_awaited_by(
14931521
handle, &local_debug_offsets, &local_async_debug,
1494-
running_task_addr, awaited_by)
1522+
running_task_addr, awaited_by, 1)
14951523
) {
14961524
goto result_err;
14971525
}
@@ -1518,13 +1546,13 @@ static PyMethodDef methods[] = {
15181546

15191547
static struct PyModuleDef module = {
15201548
.m_base = PyModuleDef_HEAD_INIT,
1521-
.m_name = "_testexternalinspection",
1549+
.m_name = "_remotedebuggingmodule",
15221550
.m_size = -1,
15231551
.m_methods = methods,
15241552
};
15251553

15261554
PyMODINIT_FUNC
1527-
PyInit__testexternalinspection(void)
1555+
PyInit__remotedebugging(void)
15281556
{
15291557
PyObject* mod = PyModule_Create(&module);
15301558
if (mod == NULL) {

PCbuild/_testexternalinspection.vcxproj renamed to PCbuild/_remotedebugging.vcxproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
</ItemGroup>
6969
<PropertyGroup Label="Globals">
7070
<ProjectGuid>{4D7C112F-3083-4D9E-9754-9341C14D9B39}</ProjectGuid>
71-
<RootNamespace>_testexternalinspection</RootNamespace>
71+
<RootNamespace>_remotedebugging</RootNamespace>
7272
<Keyword>Win32Proj</Keyword>
7373
<SupportPGO>false</SupportPGO>
7474
</PropertyGroup>
@@ -93,7 +93,7 @@
9393
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
9494
</PropertyGroup>
9595
<ItemGroup>
96-
<ClCompile Include="..\Modules\_testexternalinspection.c" />
96+
<ClCompile Include="..\Modules\_remotedebuggingmodule.c" />
9797
</ItemGroup>
9898
<ItemGroup>
9999
<ResourceCompile Include="..\PC\python_nt.rc" />

PCbuild/_testexternalinspection.vcxproj.filters renamed to PCbuild/_remotedebugging.vcxproj.filters

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</Filter>
1010
</ItemGroup>
1111
<ItemGroup>
12-
<ClCompile Include="..\Modules\_testexternalinspection.c" />
12+
<ClCompile Include="..\Modules\_remotedebuggingmodule.c" />
1313
</ItemGroup>
1414
<ItemGroup>
1515
<ResourceCompile Include="..\PC\python_nt.rc">

PCbuild/pcbuild.proj

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
<!-- pyshellext.dll -->
6767
<Projects Include="pyshellext.vcxproj" />
6868
<!-- Extension modules -->
69-
<ExtensionModules Include="_asyncio;_zoneinfo;_decimal;_elementtree;_multiprocessing;_overlapped;pyexpat;_queue;select;unicodedata;winsound;_uuid;_wmi" />
69+
<ExtensionModules Include="_asyncio;_remotedebugging;_zoneinfo;_decimal;_elementtree;_multiprocessing;_overlapped;pyexpat;_queue;select;unicodedata;winsound;_uuid;_wmi" />
7070
<ExtensionModules Include="_ctypes" Condition="$(IncludeCTypes)" />
7171
<!-- Extension modules that require external sources -->
7272
<ExternalModules Include="_bz2;_lzma;_sqlite3" />
@@ -79,7 +79,7 @@
7979
<ExtensionModules Include="@(ExternalModules->'%(Identity)')" Condition="$(IncludeExternals)" />
8080
<Projects Include="@(ExtensionModules->'%(Identity).vcxproj')" Condition="$(IncludeExtensions)" />
8181
<!-- Test modules -->
82-
<TestModules Include="_ctypes_test;_testbuffer;_testcapi;_testlimitedcapi;_testexternalinspection;_testinternalcapi;_testembed;_testimportmultiple;_testmultiphase;_testsinglephase;_testconsole;_testclinic;_testclinic_limited" />
82+
<TestModules Include="_ctypes_test;_testbuffer;_testcapi;_testlimitedcapi;_testinternalcapi;_testembed;_testimportmultiple;_testmultiphase;_testsinglephase;_testconsole;_testclinic;_testclinic_limited" />
8383
<TestModules Include="xxlimited" Condition="'$(Configuration)' == 'Release'" />
8484
<TestModules Include="xxlimited_35" Condition="'$(Configuration)' == 'Release'" />
8585
<Projects Include="@(TestModules->'%(Identity).vcxproj')" Condition="$(IncludeTests)">

PCbuild/pcbuild.sln

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testclinic", "_testclinic.
8181
EndProject
8282
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testinternalcapi", "_testinternalcapi.vcxproj", "{900342D7-516A-4469-B1AD-59A66E49A25F}"
8383
EndProject
84-
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testexternalinspection", "_testexternalinspection.vcxproj", "{4D7C112F-3083-4D9E-9754-9341C14D9B39}"
84+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_remotedebugging", "_remotedebugging.vcxproj", "{4D7C112F-3083-4D9E-9754-9341C14D9B39}"
8585
EndProject
8686
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testimportmultiple", "_testimportmultiple.vcxproj", "{36D0C52C-DF4E-45D0-8BC7-E294C3ABC781}"
8787
EndProject

Tools/build/generate_stdlib_module_names.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
'_testlimitedcapi',
3535
'_testmultiphase',
3636
'_testsinglephase',
37-
'_testexternalinspection',
37+
'_remotedebuggingmodule',
3838
'_xxtestfuzz',
3939
'idlelib.idle_test',
4040
'test',

0 commit comments

Comments
 (0)