Skip to content

Commit 7185f8d

Browse files
committed
Implement _testexternalinspection.get_async_stack_trace()
1 parent bdc71db commit 7185f8d

File tree

7 files changed

+621
-30
lines changed

7 files changed

+621
-30
lines changed

Include/internal/pycore_runtime.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ typedef struct _Py_DebugOffsets {
108108
uint64_t instr_ptr;
109109
uint64_t localsplus;
110110
uint64_t owner;
111+
uint64_t stackpointer;
111112
} interpreter_frame;
112113

113114
// Code object offset;
@@ -152,6 +153,13 @@ typedef struct _Py_DebugOffsets {
152153
uint64_t ob_size;
153154
} list_object;
154155

156+
// PySet object offset;
157+
struct _set_object {
158+
uint64_t size;
159+
uint64_t used;
160+
uint64_t table;
161+
} set_object;
162+
155163
// PyDict object offset;
156164
struct _dict_object {
157165
uint64_t size;
@@ -195,14 +203,19 @@ typedef struct _Py_DebugOffsets {
195203

196204
struct _gen_object {
197205
uint64_t size;
206+
uint64_t gi_name;
198207
uint64_t gi_iframe;
199208
uint64_t gi_task;
209+
uint64_t gi_frame_state;
200210
} gen_object;
201211

202212
struct _asyncio_task_object {
203213
uint64_t size;
204214
uint64_t task_name;
205215
uint64_t task_awaited_by;
216+
uint64_t task_is_task;
217+
uint64_t task_awaited_by_is_set;
218+
uint64_t task_coro;
206219
} asyncio_task_object;
207220
} _Py_DebugOffsets;
208221

Include/internal/pycore_runtime_init.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ typedef enum {
4444
PyObject *prefix##_cancelled_exc; \
4545
PyObject *prefix##_awaited_by; \
4646
fut_state prefix##_state; \
47+
/* Used by profilers to make traversing the stack from an external \
48+
process faster. NOTE: can't be bit fields. */ \
49+
char prefix##_is_task; \
50+
char prefix##_awaited_by_is_set; \
4751
/* These bitfields need to be at the end of the struct \
4852
so that these and bitfields from TaskObj are contiguous. \
4953
*/ \
5054
unsigned prefix##_log_tb: 1; \
5155
unsigned prefix##_blocking: 1; \
52-
/* Used by profilers to make traversing the stack from an external \
53-
process faster. */ \
54-
unsigned prefix##_is_task: 1; \
55-
unsigned prefix##_awaited_by_is_set: 1;
5656

5757
typedef struct {
5858
FutureObj_HEAD(fut)
@@ -122,6 +122,7 @@ extern PyTypeObject _PyExc_MemoryError;
122122
.instr_ptr = offsetof(_PyInterpreterFrame, instr_ptr), \
123123
.localsplus = offsetof(_PyInterpreterFrame, localsplus), \
124124
.owner = offsetof(_PyInterpreterFrame, owner), \
125+
.stackpointer = offsetof(_PyInterpreterFrame, stackpointer), \
125126
}, \
126127
.code_object = { \
127128
.size = sizeof(PyCodeObject), \
@@ -155,6 +156,11 @@ extern PyTypeObject _PyExc_MemoryError;
155156
.ob_item = offsetof(PyListObject, ob_item), \
156157
.ob_size = offsetof(PyListObject, ob_base.ob_size), \
157158
}, \
159+
.set_object = { \
160+
.size = sizeof(PySetObject), \
161+
.used = offsetof(PySetObject, used), \
162+
.table = offsetof(PySetObject, table), \
163+
}, \
158164
.dict_object = { \
159165
.size = sizeof(PyDictObject), \
160166
.ma_keys = offsetof(PyDictObject, ma_keys), \
@@ -186,13 +192,18 @@ extern PyTypeObject _PyExc_MemoryError;
186192
}, \
187193
.gen_object = { \
188194
.size = sizeof(PyGenObject), \
195+
.gi_name = offsetof(PyGenObject, gi_name), \
189196
.gi_iframe = offsetof(PyGenObject, gi_iframe), \
190197
.gi_task = offsetof(PyGenObject, gi_task), \
198+
.gi_frame_state = offsetof(PyGenObject, gi_frame_state), \
191199
}, \
192200
.asyncio_task_object = { \
193201
.size = sizeof(TaskObj), \
194202
.task_name = offsetof(TaskObj, task_name), \
195203
.task_awaited_by = offsetof(TaskObj, task_awaited_by), \
204+
.task_is_task = offsetof(TaskObj, task_is_task), \
205+
.task_awaited_by_is_set = offsetof(TaskObj, task_awaited_by_is_set), \
206+
.task_coro = offsetof(TaskObj, task_coro), \
196207
}, \
197208
}, \
198209
.allocators = { \

Lib/test/test_asyncio/test_stack.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ def tearDownModule():
77
asyncio.set_event_loop_policy(None)
88

99

10-
def capture_test_stack(*, fut=None):
10+
def capture_test_stack(*, fut=None, anon=True):
1111

1212
def walk(s):
1313
ret = [
14-
(f"T<{n}>" if '-' not in (n := s.future.get_name()) else 'T<anon>')
15-
if isinstance(s.future, asyncio.Task) else 'F'
14+
(f"T<{s.future.get_name()}>"
15+
if not anon or '-' not in s.future.get_name() else 'T<anon>'
16+
) if isinstance(s.future, asyncio.Task) else 'F'
1617
]
1718

1819
ret.append(

Modules/_asynciomodule.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,6 @@ set_task_coro(TaskObj *task, PyObject *coro)
213213
assert(coro != NULL);
214214
if (PyCoro_CheckExact(coro)) {
215215
_PyCoro_SetTask(coro, (PyObject *)task);
216-
printf("SET %p\n", task);
217216
}
218217
Py_INCREF(coro);
219218
Py_XSETREF(task->task_coro, coro);

0 commit comments

Comments
 (0)