Coverage Report

Created: 2026-10-17 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Modules/_asynciomodule.c
Line
Count
Source
1
#ifndef Py_BUILD_CORE_BUILTIN
2
#  define Py_BUILD_CORE_MODULE 1
3
#endif
4
5
#include "Python.h"
6
#include "pycore_freelist.h"      // _Py_FREELIST_POP()
7
#include "pycore_genobject.h"
8
#include "pycore_llist.h"         // struct llist_node
9
#include "pycore_list.h"          // _PyList_AppendTakeRef()
10
#include "pycore_modsupport.h"    // _PyArg_CheckPositional()
11
#include "pycore_moduleobject.h"  // _PyModule_GetState()
12
#include "pycore_object.h"        // _PyObject_SetMaybeWeakref
13
#include "pycore_pylifecycle.h"   // _Py_IsInterpreterFinalizing()
14
#include "pycore_pystate.h"       // _PyThreadState_GET()
15
#include "pycore_runtime_init.h"  // _Py_ID()
16
#include "pycore_tuple.h"         // _PyTuple_FromPair
17
18
#include <stddef.h>               // offsetof()
19
20
21
/*[clinic input]
22
module _asyncio
23
[clinic start generated code]*/
24
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
25
26
typedef enum {
27
    STATE_PENDING,
28
    STATE_CANCELLED,
29
    STATE_FINISHED
30
} fut_state;
31
32
#define FutureObj_HEAD(prefix)                                              \
33
    PyObject_HEAD                                                           \
34
    PyObject *prefix##_loop;                                                \
35
    PyObject *prefix##_callback0;                                           \
36
    PyObject *prefix##_context0;                                            \
37
    PyObject *prefix##_callbacks;                                           \
38
    PyObject *prefix##_exception;                                           \
39
    PyObject *prefix##_exception_tb;                                        \
40
    PyObject *prefix##_result;                                              \
41
    PyObject *prefix##_source_tb;                                           \
42
    PyObject *prefix##_cancel_msg;                                          \
43
    PyObject *prefix##_cancelled_exc;                                       \
44
    PyObject *prefix##_awaited_by;                                          \
45
    fut_state prefix##_state;                                               \
46
    /* Used by profilers to make traversing the stack from an external      \
47
       process faster. */                                                   \
48
    char prefix##_is_task;                                                  \
49
    char prefix##_awaited_by_is_set;                                        \
50
    /* These bitfields need to be at the end of the struct                  \
51
       so that these and bitfields from TaskObj are contiguous.             \
52
    */                                                                      \
53
    unsigned prefix##_log_tb: 1;                                            \
54
    unsigned prefix##_blocking: 1;                                          \
55
56
typedef struct {
57
    FutureObj_HEAD(fut)
58
} FutureObj;
59
60
typedef struct TaskObj {
61
    FutureObj_HEAD(task)
62
    unsigned task_must_cancel: 1;
63
    unsigned task_log_destroy_pending: 1;
64
    int task_num_cancels_requested;
65
    PyObject *task_fut_waiter;
66
    PyObject *task_coro;
67
    PyObject *task_name;
68
    PyObject *task_context;
69
    struct llist_node task_node;
70
#ifdef Py_GIL_DISABLED
71
    // thread id of the thread where this task was created
72
    uintptr_t task_tid;
73
#endif
74
} TaskObj;
75
76
typedef struct {
77
    PyObject_HEAD
78
    TaskObj *sw_task;
79
    PyObject *sw_arg;
80
} TaskStepMethWrapper;
81
82
0
#define Future_CheckExact(state, obj) Py_IS_TYPE(obj, state->FutureType)
83
0
#define Task_CheckExact(state, obj) Py_IS_TYPE(obj, state->TaskType)
84
85
#define Future_Check(state, obj)                        \
86
    (Future_CheckExact(state, obj)                      \
87
     || PyObject_TypeCheck(obj, state->FutureType))
88
89
#define Task_Check(state, obj)                          \
90
0
    (Task_CheckExact(state, obj)                        \
91
0
     || PyObject_TypeCheck(obj, state->TaskType))
92
93
// This macro is optimized to quickly return for native Future *or* Task
94
// objects by inlining fast "exact" checks to be called first.
95
#define TaskOrFuture_Check(state, obj)                  \
96
0
    (Task_CheckExact(state, obj)                        \
97
0
     || Future_CheckExact(state, obj)                   \
98
0
     || PyObject_TypeCheck(obj, state->FutureType)      \
99
0
     || PyObject_TypeCheck(obj, state->TaskType))
100
101
typedef struct _Py_AsyncioModuleDebugOffsets {
102
    struct _asyncio_task_object {
103
        uint64_t size;
104
        uint64_t task_name;
105
        uint64_t task_awaited_by;
106
        uint64_t task_is_task;
107
        uint64_t task_awaited_by_is_set;
108
        uint64_t task_coro;
109
        uint64_t task_node;
110
    } asyncio_task_object;
111
    struct _asyncio_interpreter_state {
112
        uint64_t size;
113
        uint64_t asyncio_tasks_head;
114
    } asyncio_interpreter_state;
115
    struct _asyncio_thread_state {
116
        uint64_t size;
117
        uint64_t asyncio_running_loop;
118
        uint64_t asyncio_running_task;
119
        uint64_t asyncio_tasks_head;
120
    } asyncio_thread_state;
121
} Py_AsyncioModuleDebugOffsets;
122
123
GENERATE_DEBUG_SECTION(AsyncioDebug, Py_AsyncioModuleDebugOffsets _Py_AsyncioDebug)
124
    = {.asyncio_task_object = {
125
           .size = sizeof(TaskObj),
126
           .task_name = offsetof(TaskObj, task_name),
127
           .task_awaited_by = offsetof(TaskObj, task_awaited_by),
128
           .task_is_task = offsetof(TaskObj, task_is_task),
129
           .task_awaited_by_is_set = offsetof(TaskObj, task_awaited_by_is_set),
130
           .task_coro = offsetof(TaskObj, task_coro),
131
           .task_node = offsetof(TaskObj, task_node),
132
       },
133
       .asyncio_interpreter_state = {
134
            .size = sizeof(PyInterpreterState),
135
            .asyncio_tasks_head = offsetof(PyInterpreterState, asyncio_tasks_head),
136
       },
137
       .asyncio_thread_state = {
138
           .size = sizeof(_PyThreadStateImpl),
139
           .asyncio_running_loop = offsetof(_PyThreadStateImpl, asyncio_running_loop),
140
           .asyncio_running_task = offsetof(_PyThreadStateImpl, asyncio_running_task),
141
           .asyncio_tasks_head = offsetof(_PyThreadStateImpl, asyncio_tasks_head),
142
       }};
143
144
/* State of the _asyncio module */
145
typedef struct {
146
    PyTypeObject *FutureIterType;
147
    PyTypeObject *TaskStepMethWrapper_Type;
148
    PyTypeObject *FutureType;
149
    PyTypeObject *TaskType;
150
151
    PyObject *asyncio_mod;
152
    PyObject *context_kwname;
153
154
    /* WeakSet containing scheduled 3rd party tasks which don't
155
       inherit from native asyncio.Task */
156
    PyObject *non_asyncio_tasks;
157
158
    /* Set containing all 3rd party eagerly executing tasks which don't
159
       inherit from native asyncio.Task */
160
    PyObject *non_asyncio_eager_tasks;
161
162
    /* An isinstance type cache for the 'is_coroutine()' function. */
163
    PyObject *iscoroutine_typecache;
164
165
    /* Imports from asyncio.events. */
166
    PyObject *asyncio_get_event_loop;
167
168
    /* Imports from asyncio.base_futures. */
169
    PyObject *asyncio_future_repr_func;
170
171
    /* Imports from asyncio.exceptions. */
172
    PyObject *asyncio_CancelledError;
173
    PyObject *asyncio_InvalidStateError;
174
175
    /* Imports from asyncio.base_tasks. */
176
    PyObject *asyncio_task_get_stack_func;
177
    PyObject *asyncio_task_print_stack_func;
178
    PyObject *asyncio_task_repr_func;
179
180
    /* Imports from asyncio.coroutines. */
181
    PyObject *asyncio_iscoroutine_func;
182
183
    /* Imports from traceback. */
184
    PyObject *traceback_extract_stack;
185
186
    /* Counter for autogenerated Task names */
187
    uint64_t task_name_counter;
188
189
    /* Pointer to the asyncio debug offset to avoid it to be optimized away
190
       by the compiler */
191
    void *debug_offsets;
192
193
} asyncio_state;
194
195
static inline asyncio_state *
196
get_asyncio_state(PyObject *mod)
197
0
{
198
0
    asyncio_state *state = _PyModule_GetState(mod);
199
0
    assert(state != NULL);
200
0
    return state;
201
0
}
202
203
static inline asyncio_state *
204
get_asyncio_state_by_cls(PyTypeObject *cls)
205
0
{
206
0
    asyncio_state *state = (asyncio_state *)_PyType_GetModuleState(cls);
207
0
    assert(state != NULL);
208
0
    return state;
209
0
}
210
211
static struct PyModuleDef _asynciomodule;
212
213
static inline asyncio_state *
214
get_asyncio_state_by_def(PyObject *self)
215
0
{
216
0
    PyTypeObject *tp = Py_TYPE(self);
217
0
    PyObject *mod = PyType_GetModuleByDef(tp, &_asynciomodule);
218
0
    assert(mod != NULL);
219
0
    return get_asyncio_state(mod);
220
0
}
221
222
#include "clinic/_asynciomodule.c.h"
223
224
225
/*[clinic input]
226
class _asyncio.Future "FutureObj *" "&Future_Type"
227
[clinic start generated code]*/
228
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
229
230
231
/* Get FutureIter from Future */
232
static PyObject * future_new_iter(PyObject *);
233
234
static PyObject *
235
task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *result);
236
static void unregister_task(TaskObj *task);
237
238
static void
239
clear_task_coro(TaskObj *task)
240
0
{
241
0
    Py_CLEAR(task->task_coro);
242
0
}
243
244
245
static void
246
set_task_coro(TaskObj *task, PyObject *coro)
247
0
{
248
0
    assert(coro != NULL);
249
0
    Py_INCREF(coro);
250
0
    Py_XSETREF(task->task_coro, coro);
251
0
}
252
253
254
static int
255
_is_coroutine(asyncio_state *state, PyObject *coro)
256
0
{
257
    /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
258
       to check if it's another coroutine flavour.
259
260
       Do this check after 'future_init()'; in case we need to raise
261
       an error, __del__ needs a properly initialized object.
262
    */
263
0
    PyObject *res = PyObject_CallOneArg(state->asyncio_iscoroutine_func, coro);
264
0
    if (res == NULL) {
265
0
        return -1;
266
0
    }
267
268
0
    int is_res_true = PyObject_IsTrue(res);
269
0
    Py_DECREF(res);
270
0
    if (is_res_true <= 0) {
271
0
        return is_res_true;
272
0
    }
273
274
0
    if (PySet_GET_SIZE(state->iscoroutine_typecache) < 100) {
275
        /* Just in case we don't want to cache more than 100
276
           positive types.  That shouldn't ever happen, unless
277
           someone stressing the system on purpose.
278
        */
279
0
        if (PySet_Add(state->iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
280
0
            return -1;
281
0
        }
282
0
    }
283
284
0
    return 1;
285
0
}
286
287
288
static inline int
289
is_coroutine(asyncio_state *state, PyObject *coro)
290
0
{
291
0
    if (PyCoro_CheckExact(coro)) {
292
0
        return 1;
293
0
    }
294
295
    /* Check if `type(coro)` is in the cache.
296
       Caching makes is_coroutine() function almost as fast as
297
       PyCoro_CheckExact() for non-native coroutine-like objects
298
       (like coroutines compiled with Cython).
299
300
       asyncio.iscoroutine() has its own type caching mechanism.
301
       This cache allows us to avoid the cost of even calling
302
       a pure-Python function in 99.9% cases.
303
    */
304
0
    int has_it = PySet_Contains(
305
0
        state->iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
306
0
    if (has_it == 0) {
307
        /* type(coro) is not in iscoroutine_typecache */
308
0
        return _is_coroutine(state, coro);
309
0
    }
310
311
    /* either an error has occurred or
312
       type(coro) is in iscoroutine_typecache
313
    */
314
0
    return has_it;
315
0
}
316
317
318
static PyObject *
319
get_future_loop(asyncio_state *state, PyObject *fut)
320
0
{
321
    /* Implementation of `asyncio.futures._get_loop` */
322
323
0
    PyObject *getloop;
324
325
0
    if (Future_CheckExact(state, fut) || Task_CheckExact(state, fut)) {
326
0
        PyObject *loop = ((FutureObj *)fut)->fut_loop;
327
0
        return Py_NewRef(loop);
328
0
    }
329
330
0
    if (PyObject_GetOptionalAttr(fut, &_Py_ID(get_loop), &getloop) < 0) {
331
0
        return NULL;
332
0
    }
333
0
    if (getloop != NULL) {
334
0
        PyObject *res = PyObject_CallNoArgs(getloop);
335
0
        Py_DECREF(getloop);
336
0
        return res;
337
0
    }
338
339
0
    return PyObject_GetAttr(fut, &_Py_ID(_loop));
340
0
}
341
342
static PyObject *
343
get_event_loop(asyncio_state *state)
344
0
{
345
0
    PyObject *loop;
346
347
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
348
0
    loop = Py_XNewRef(ts->asyncio_running_loop);
349
350
0
    if (loop != NULL) {
351
0
        return loop;
352
0
    }
353
354
0
    return PyObject_CallNoArgs(state->asyncio_get_event_loop);
355
0
}
356
357
358
static int
359
call_soon(asyncio_state *state, PyObject *loop, PyObject *func, PyObject *arg,
360
          PyObject *ctx)
361
0
{
362
0
    PyObject *handle;
363
364
0
    if (ctx == NULL) {
365
0
        PyObject *stack[] = {loop, func, arg};
366
0
        size_t nargsf = 3 | PY_VECTORCALL_ARGUMENTS_OFFSET;
367
0
        handle = PyObject_VectorcallMethod(&_Py_ID(call_soon), stack, nargsf, NULL);
368
0
    }
369
0
    else {
370
        /* All refs in 'stack' are borrowed. */
371
0
        PyObject *stack[4];
372
0
        size_t nargs = 2;
373
0
        stack[0] = loop;
374
0
        stack[1] = func;
375
0
        if (arg != NULL) {
376
0
            stack[2] = arg;
377
0
            nargs++;
378
0
        }
379
0
        stack[nargs] = (PyObject *)ctx;
380
0
        size_t nargsf = nargs | PY_VECTORCALL_ARGUMENTS_OFFSET;
381
0
        handle = PyObject_VectorcallMethod(&_Py_ID(call_soon), stack, nargsf,
382
0
                                           state->context_kwname);
383
0
    }
384
385
0
    if (handle == NULL) {
386
0
        return -1;
387
0
    }
388
0
    Py_DECREF(handle);
389
0
    return 0;
390
0
}
391
392
393
static inline int
394
future_is_alive(FutureObj *fut)
395
0
{
396
0
    return fut->fut_loop != NULL;
397
0
}
398
399
400
static inline int
401
future_ensure_alive(FutureObj *fut)
402
0
{
403
0
    if (!future_is_alive(fut)) {
404
0
        PyErr_SetString(PyExc_RuntimeError,
405
0
                        "Future object is not initialized.");
406
0
        return -1;
407
0
    }
408
0
    return 0;
409
0
}
410
411
412
#define ENSURE_FUTURE_ALIVE(state, fut)                             \
413
0
    do {                                                            \
414
0
        assert(Future_Check(state, fut) || Task_Check(state, fut)); \
415
0
        (void)state;                                                \
416
0
        if (future_ensure_alive((FutureObj*)fut)) {                 \
417
0
            return NULL;                                            \
418
0
        }                                                           \
419
0
    } while(0);
420
421
422
static int
423
future_schedule_callbacks(asyncio_state *state, FutureObj *fut)
424
0
{
425
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
426
427
0
    assert(fut->fut_state != STATE_PENDING);
428
429
0
    if (Task_Check(state, fut)) {
430
        // remove task from linked-list of tasks
431
        // as it is finished now
432
0
        TaskObj *task = (TaskObj *)fut;
433
0
        unregister_task(task);
434
0
    }
435
436
0
    if (fut->fut_callback0 != NULL) {
437
        /* There's a 1st callback */
438
439
        // Beware: An evil call_soon could alter fut_callback0 or fut_context0.
440
        // Since we are anyway clearing them after the call, whether call_soon
441
        // succeeds or not, the idea is to transfer ownership so that external
442
        // code is not able to alter them during the call.
443
0
        PyObject *fut_callback0 = fut->fut_callback0;
444
0
        fut->fut_callback0 = NULL;
445
0
        PyObject *fut_context0 = fut->fut_context0;
446
0
        fut->fut_context0 = NULL;
447
448
0
        int ret = call_soon(state, fut->fut_loop, fut_callback0,
449
0
                            (PyObject *)fut, fut_context0);
450
0
        Py_CLEAR(fut_callback0);
451
0
        Py_CLEAR(fut_context0);
452
0
        if (ret) {
453
            /* If an error occurs in pure-Python implementation,
454
               all callbacks are cleared. */
455
0
            Py_CLEAR(fut->fut_callbacks);
456
0
            return ret;
457
0
        }
458
459
        /* we called the first callback, now try calling
460
           callbacks from the 'fut_callbacks' list. */
461
0
    }
462
463
0
    if (fut->fut_callbacks == NULL) {
464
        /* No more callbacks, return. */
465
0
        return 0;
466
0
    }
467
468
    // Beware: An evil call_soon could change fut->fut_callbacks.
469
    // The idea is to transfer the ownership of the callbacks list
470
    // so that external code is not able to mutate the list during
471
    // the iteration.
472
0
    PyObject *callbacks = fut->fut_callbacks;
473
0
    fut->fut_callbacks = NULL;
474
0
    Py_ssize_t n = PyList_GET_SIZE(callbacks);
475
0
    for (Py_ssize_t i = 0; i < n; i++) {
476
0
        assert(PyList_GET_SIZE(callbacks) == n);
477
0
        PyObject *cb_tup = PyList_GET_ITEM(callbacks, i);
478
0
        PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
479
0
        PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
480
481
0
        if (call_soon(state, fut->fut_loop, cb, (PyObject *)fut, ctx)) {
482
0
            Py_DECREF(callbacks);
483
0
            return -1;
484
0
        }
485
0
    }
486
0
    Py_DECREF(callbacks);
487
0
    return 0;
488
0
}
489
490
491
static int
492
future_init(FutureObj *fut, PyObject *loop)
493
0
{
494
0
    if (fut->fut_loop != NULL) {
495
0
        PyErr_Format(PyExc_RuntimeError, "%T object is already initialized", fut);
496
0
        return -1;
497
0
    }
498
499
0
    PyObject *res;
500
0
    int is_true;
501
0
    fut->fut_state = STATE_PENDING;
502
0
    fut->fut_log_tb = 0;
503
0
    fut->fut_blocking = 0;
504
0
    fut->fut_awaited_by_is_set = 0;
505
0
    fut->fut_is_task = 0;
506
507
0
    if (loop == Py_None) {
508
0
        asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
509
0
        loop = get_event_loop(state);
510
0
        if (loop == NULL) {
511
0
            return -1;
512
0
        }
513
0
    }
514
0
    else {
515
0
        Py_INCREF(loop);
516
0
    }
517
0
    fut->fut_loop = loop;
518
519
0
    res = PyObject_CallMethodNoArgs(fut->fut_loop, &_Py_ID(get_debug));
520
0
    if (res == NULL) {
521
0
        return -1;
522
0
    }
523
0
    is_true = PyObject_IsTrue(res);
524
0
    Py_DECREF(res);
525
0
    if (is_true < 0) {
526
0
        return -1;
527
0
    }
528
0
    if (is_true && !_Py_IsInterpreterFinalizing(_PyInterpreterState_GET())) {
529
        /* Only try to capture the traceback if the interpreter is not being
530
           finalized.  The original motivation to add a `Py_IsFinalizing()`
531
           call was to prevent SIGSEGV when a Future is created in a __del__
532
           method, which is called during the interpreter shutdown and the
533
           traceback module is already unloaded.
534
        */
535
0
        asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
536
0
        fut->fut_source_tb = PyObject_CallNoArgs(state->traceback_extract_stack);
537
0
        if (fut->fut_source_tb == NULL) {
538
0
            return -1;
539
0
        }
540
0
    }
541
542
0
    return 0;
543
0
}
544
545
static int
546
future_awaited_by_add(asyncio_state *state, FutureObj *fut, PyObject *thing)
547
0
{
548
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
549
    // We only want to support native asyncio Futures.
550
    // For further insight see the comment in the Python
551
    // implementation of "future_add_to_awaited_by()".
552
0
    assert(TaskOrFuture_Check(state, fut));
553
0
    assert(TaskOrFuture_Check(state, thing));
554
555
    /* Most futures/task are only awaited by one entity, so we want
556
       to avoid always creating a set for `fut_awaited_by`.
557
    */
558
0
    if (fut->fut_awaited_by == NULL) {
559
0
        assert(!fut->fut_awaited_by_is_set);
560
0
        Py_INCREF(thing);
561
0
        fut->fut_awaited_by = thing;
562
0
        return 0;
563
0
    }
564
565
0
    if (fut->fut_awaited_by_is_set) {
566
0
        assert(PySet_CheckExact(fut->fut_awaited_by));
567
0
        return PySet_Add(fut->fut_awaited_by, thing);
568
0
    }
569
570
0
    PyObject *set = PySet_New(NULL);
571
0
    if (set == NULL) {
572
0
        return -1;
573
0
    }
574
0
    if (PySet_Add(set, thing)) {
575
0
        Py_DECREF(set);
576
0
        return -1;
577
0
    }
578
0
    if (PySet_Add(set, fut->fut_awaited_by)) {
579
0
        Py_DECREF(set);
580
0
        return -1;
581
0
    }
582
0
    Py_SETREF(fut->fut_awaited_by, set);
583
0
    fut->fut_awaited_by_is_set = 1;
584
0
    return 0;
585
0
}
586
587
static int
588
future_awaited_by_discard(asyncio_state *state, FutureObj *fut, PyObject *thing)
589
0
{
590
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
591
    // We only want to support native asyncio Futures.
592
    // For further insight see the comment in the Python
593
    // implementation of "future_add_to_awaited_by()".
594
0
    assert(TaskOrFuture_Check(state, fut));
595
0
    assert(TaskOrFuture_Check(state, thing));
596
597
    /* Following the semantics of 'set.discard()' here in not
598
       raising an error if `thing` isn't in the `awaited_by` "set".
599
    */
600
0
    if (fut->fut_awaited_by == NULL) {
601
0
        return 0;
602
0
    }
603
0
    if (fut->fut_awaited_by == thing) {
604
0
        Py_CLEAR(fut->fut_awaited_by);
605
0
        return 0;
606
0
    }
607
0
    if (fut->fut_awaited_by_is_set) {
608
0
        assert(PySet_CheckExact(fut->fut_awaited_by));
609
0
        int err = PySet_Discard(fut->fut_awaited_by, thing);
610
0
        if (err < 0) {
611
0
            return -1;
612
0
        } else {
613
0
            return 0;
614
0
        }
615
0
    }
616
0
    return 0;
617
0
}
618
619
620
static PyObject *
621
future_set_result(asyncio_state *state, FutureObj *fut, PyObject *res)
622
0
{
623
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
624
625
0
    if (future_ensure_alive(fut)) {
626
0
        return NULL;
627
0
    }
628
629
0
    if (fut->fut_state != STATE_PENDING) {
630
0
        PyErr_SetString(state->asyncio_InvalidStateError, "invalid state");
631
0
        return NULL;
632
0
    }
633
634
0
    assert(!fut->fut_result);
635
0
    fut->fut_result = Py_NewRef(res);
636
0
    fut->fut_state = STATE_FINISHED;
637
638
0
    if (future_schedule_callbacks(state, fut) == -1) {
639
0
        return NULL;
640
0
    }
641
0
    Py_RETURN_NONE;
642
0
}
643
644
static PyObject *
645
future_set_exception(asyncio_state *state, FutureObj *fut, PyObject *exc)
646
0
{
647
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
648
649
0
    PyObject *exc_val = NULL;
650
651
0
    if (fut->fut_state != STATE_PENDING) {
652
0
        PyErr_SetString(state->asyncio_InvalidStateError, "invalid state");
653
0
        return NULL;
654
0
    }
655
656
0
    if (PyExceptionClass_Check(exc)) {
657
0
        exc_val = PyObject_CallNoArgs(exc);
658
0
        if (exc_val == NULL) {
659
0
            return NULL;
660
0
        }
661
0
        if (fut->fut_state != STATE_PENDING) {
662
0
            Py_DECREF(exc_val);
663
0
            PyErr_SetString(state->asyncio_InvalidStateError, "invalid state");
664
0
            return NULL;
665
0
        }
666
0
    }
667
0
    else {
668
0
        exc_val = Py_NewRef(exc);
669
0
    }
670
0
    if (!PyExceptionInstance_Check(exc_val)) {
671
0
        Py_DECREF(exc_val);
672
0
        PyErr_SetString(PyExc_TypeError, "invalid exception object");
673
0
        return NULL;
674
0
    }
675
0
    if (PyErr_GivenExceptionMatches(exc_val, PyExc_StopIteration)) {
676
0
        const char *msg = "StopIteration interacts badly with "
677
0
                          "generators and cannot be raised into a "
678
0
                          "Future";
679
0
        PyObject *message = PyUnicode_FromString(msg);
680
0
        if (message == NULL) {
681
0
            Py_DECREF(exc_val);
682
0
            return NULL;
683
0
        }
684
0
        PyObject *err = PyObject_CallOneArg(PyExc_RuntimeError, message);
685
0
        Py_DECREF(message);
686
0
        if (err == NULL) {
687
0
            Py_DECREF(exc_val);
688
0
            return NULL;
689
0
        }
690
0
        assert(PyExceptionInstance_Check(err));
691
692
0
        PyException_SetCause(err, Py_NewRef(exc_val));
693
0
        PyException_SetContext(err, Py_NewRef(exc_val));
694
0
        Py_DECREF(exc_val);
695
0
        exc_val = err;
696
0
    }
697
698
0
    assert(!fut->fut_exception);
699
0
    assert(!fut->fut_exception_tb);
700
0
    fut->fut_exception = exc_val;
701
0
    fut->fut_exception_tb = PyException_GetTraceback(exc_val);
702
0
    fut->fut_state = STATE_FINISHED;
703
704
0
    if (future_schedule_callbacks(state, fut) == -1) {
705
0
        return NULL;
706
0
    }
707
708
0
    fut->fut_log_tb = 1;
709
0
    Py_RETURN_NONE;
710
0
}
711
712
static PyObject *
713
create_cancelled_error(asyncio_state *state, FutureObj *fut)
714
0
{
715
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
716
717
0
    PyObject *exc;
718
0
    if (fut->fut_cancelled_exc != NULL) {
719
        /* transfer ownership */
720
0
        exc = fut->fut_cancelled_exc;
721
0
        fut->fut_cancelled_exc = NULL;
722
0
        return exc;
723
0
    }
724
0
    PyObject *msg = fut->fut_cancel_msg;
725
0
    if (msg == NULL || msg == Py_None) {
726
0
        exc = PyObject_CallNoArgs(state->asyncio_CancelledError);
727
0
    } else {
728
0
        exc = PyObject_CallOneArg(state->asyncio_CancelledError, msg);
729
0
    }
730
0
    return exc;
731
0
}
732
733
static void
734
future_set_cancelled_error(asyncio_state *state, FutureObj *fut)
735
0
{
736
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
737
738
0
    PyObject *exc = create_cancelled_error(state, fut);
739
0
    if (exc == NULL) {
740
0
        return;
741
0
    }
742
0
    PyErr_SetObject(state->asyncio_CancelledError, exc);
743
0
    Py_DECREF(exc);
744
0
}
745
746
static int
747
future_get_result(asyncio_state *state, FutureObj *fut, PyObject **result)
748
0
{
749
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
750
751
0
    if (fut->fut_state == STATE_CANCELLED) {
752
0
        future_set_cancelled_error(state, fut);
753
0
        return -1;
754
0
    }
755
756
0
    if (fut->fut_state != STATE_FINISHED) {
757
0
        PyErr_SetString(state->asyncio_InvalidStateError,
758
0
                        "Result is not set.");
759
0
        return -1;
760
0
    }
761
762
0
    fut->fut_log_tb = 0;
763
0
    if (fut->fut_exception != NULL) {
764
0
        PyObject *tb = fut->fut_exception_tb;
765
0
        if (tb == NULL) {
766
0
            tb = Py_None;
767
0
        }
768
0
        if (PyException_SetTraceback(fut->fut_exception, tb) < 0) {
769
0
            return -1;
770
0
        }
771
0
        *result = Py_NewRef(fut->fut_exception);
772
0
        return 1;
773
0
    }
774
775
0
    *result = Py_NewRef(fut->fut_result);
776
0
    return 0;
777
0
}
778
779
static PyObject *
780
future_add_done_callback(asyncio_state *state, FutureObj *fut, PyObject *arg,
781
                         PyObject *ctx)
782
0
{
783
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
784
785
0
    if (!future_is_alive(fut)) {
786
0
        PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
787
0
        return NULL;
788
0
    }
789
790
0
    if (fut->fut_state != STATE_PENDING) {
791
        /* The future is done/cancelled, so schedule the callback
792
           right away. */
793
0
        if (call_soon(state, fut->fut_loop, arg, (PyObject*) fut, ctx)) {
794
0
            return NULL;
795
0
        }
796
0
    }
797
0
    else {
798
        /* The future is pending, add a callback.
799
800
           Callbacks in the future object are stored as follows:
801
802
              callback0 -- a pointer to the first callback
803
              callbacks -- a list of 2nd, 3rd, ... callbacks
804
805
           Invariants:
806
807
            * callbacks != NULL:
808
                There are some callbacks in the list.  Just
809
                add the new callback to it.
810
811
            * callbacks == NULL and callback0 == NULL:
812
                This is the first callback.  Set it to callback0.
813
814
            * callbacks == NULL and callback0 != NULL:
815
                This is a second callback.  Initialize callbacks
816
                with a new list and add the new callback to it.
817
        */
818
819
0
        if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
820
0
            fut->fut_callback0 = Py_NewRef(arg);
821
0
            fut->fut_context0 = Py_NewRef(ctx);
822
0
        }
823
0
        else {
824
0
            PyObject *tup = _PyTuple_FromPair(arg, (PyObject *)ctx);
825
0
            if (tup == NULL) {
826
0
                return NULL;
827
0
            }
828
829
0
            if (fut->fut_callbacks != NULL) {
830
0
                int err = PyList_Append(fut->fut_callbacks, tup);
831
0
                if (err) {
832
0
                    Py_DECREF(tup);
833
0
                    return NULL;
834
0
                }
835
0
                Py_DECREF(tup);
836
0
            }
837
0
            else {
838
0
                fut->fut_callbacks = PyList_New(1);
839
0
                if (fut->fut_callbacks == NULL) {
840
0
                    Py_DECREF(tup);
841
0
                    return NULL;
842
0
                }
843
844
0
                PyList_SET_ITEM(fut->fut_callbacks, 0, tup);  /* borrow */
845
0
            }
846
0
        }
847
0
    }
848
849
0
    Py_RETURN_NONE;
850
0
}
851
852
static PyObject *
853
future_cancel(asyncio_state *state, FutureObj *fut, PyObject *msg)
854
0
{
855
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
856
857
0
    fut->fut_log_tb = 0;
858
859
0
    if (fut->fut_state != STATE_PENDING) {
860
0
        Py_RETURN_FALSE;
861
0
    }
862
0
    fut->fut_state = STATE_CANCELLED;
863
864
0
    Py_XINCREF(msg);
865
0
    Py_XSETREF(fut->fut_cancel_msg, msg);
866
867
0
    if (future_schedule_callbacks(state, fut) == -1) {
868
0
        return NULL;
869
0
    }
870
871
0
    Py_RETURN_TRUE;
872
0
}
873
874
/*[clinic input]
875
_asyncio.Future.__init__
876
877
    *
878
    loop: object = None
879
880
This class is *almost* compatible with concurrent.futures.Future.
881
882
    Differences:
883
884
    - result() and exception() do not take a timeout argument and
885
      raise an exception when the future isn't done yet.
886
887
    - Callbacks registered with add_done_callback() are always called
888
      via the event loop's call_soon_threadsafe().
889
890
    - This class is not compatible with the wait() and as_completed()
891
      methods in the concurrent.futures package.
892
[clinic start generated code]*/
893
894
static int
895
_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
896
/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
897
898
0
{
899
0
    return future_init(self, loop);
900
0
}
901
902
static int
903
FutureObj_clear(PyObject *op)
904
0
{
905
0
    FutureObj *fut = (FutureObj*)op;
906
0
    Py_CLEAR(fut->fut_loop);
907
0
    Py_CLEAR(fut->fut_callback0);
908
0
    Py_CLEAR(fut->fut_context0);
909
0
    Py_CLEAR(fut->fut_callbacks);
910
0
    Py_CLEAR(fut->fut_result);
911
0
    Py_CLEAR(fut->fut_exception);
912
0
    Py_CLEAR(fut->fut_exception_tb);
913
0
    Py_CLEAR(fut->fut_source_tb);
914
0
    Py_CLEAR(fut->fut_cancel_msg);
915
0
    Py_CLEAR(fut->fut_cancelled_exc);
916
0
    Py_CLEAR(fut->fut_awaited_by);
917
0
    fut->fut_awaited_by_is_set = 0;
918
0
    PyObject_ClearManagedDict((PyObject *)fut);
919
0
    return 0;
920
0
}
921
922
static int
923
FutureObj_traverse(PyObject *op, visitproc visit, void *arg)
924
0
{
925
0
    FutureObj *fut = (FutureObj*)op;
926
0
    Py_VISIT(Py_TYPE(fut));
927
0
    Py_VISIT(fut->fut_loop);
928
0
    Py_VISIT(fut->fut_callback0);
929
0
    Py_VISIT(fut->fut_context0);
930
0
    Py_VISIT(fut->fut_callbacks);
931
0
    Py_VISIT(fut->fut_result);
932
0
    Py_VISIT(fut->fut_exception);
933
0
    Py_VISIT(fut->fut_exception_tb);
934
0
    Py_VISIT(fut->fut_source_tb);
935
0
    Py_VISIT(fut->fut_cancel_msg);
936
0
    Py_VISIT(fut->fut_cancelled_exc);
937
0
    Py_VISIT(fut->fut_awaited_by);
938
0
    return PyObject_VisitManagedDict((PyObject *)fut, visit, arg);
939
0
}
940
941
/*[clinic input]
942
@critical_section
943
_asyncio.Future.result
944
945
Return the result this future represents.
946
947
If the future has been cancelled, raises CancelledError.  If the
948
future's result isn't yet available, raises InvalidStateError.  If
949
the future is done and has an exception set, this exception is
950
raised.
951
[clinic start generated code]*/
952
953
static PyObject *
954
_asyncio_Future_result_impl(FutureObj *self)
955
/*[clinic end generated code: output=f35f940936a4b1e5 input=ee20e126776cbb04]*/
956
0
{
957
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
958
0
    PyObject *result;
959
960
0
    if (!future_is_alive(self)) {
961
0
        PyErr_SetString(state->asyncio_InvalidStateError,
962
0
                        "Future object is not initialized.");
963
0
        return NULL;
964
0
    }
965
966
0
    int res = future_get_result(state, self, &result);
967
968
0
    if (res == -1) {
969
0
        return NULL;
970
0
    }
971
972
0
    if (res == 0) {
973
0
        return result;
974
0
    }
975
976
0
    assert(res == 1);
977
978
0
    PyErr_SetObject(PyExceptionInstance_Class(result), result);
979
0
    Py_DECREF(result);
980
0
    return NULL;
981
0
}
982
983
/*[clinic input]
984
@critical_section
985
_asyncio.Future.exception
986
987
    cls: defining_class
988
    /
989
990
Return the exception that was set on this future.
991
992
The exception (or None if no exception was set) is returned only if
993
the future is done.  If the future has been cancelled, raises
994
CancelledError.  If the future isn't done yet, raises
995
InvalidStateError.
996
[clinic start generated code]*/
997
998
static PyObject *
999
_asyncio_Future_exception_impl(FutureObj *self, PyTypeObject *cls)
1000
/*[clinic end generated code: output=ce75576b187c905b input=647d1fd1fc403301]*/
1001
0
{
1002
0
    if (!future_is_alive(self)) {
1003
0
        asyncio_state *state = get_asyncio_state_by_cls(cls);
1004
0
        PyErr_SetString(state->asyncio_InvalidStateError,
1005
0
                        "Future object is not initialized.");
1006
0
        return NULL;
1007
0
    }
1008
1009
0
    if (self->fut_state == STATE_CANCELLED) {
1010
0
        asyncio_state *state = get_asyncio_state_by_cls(cls);
1011
0
        future_set_cancelled_error(state, self);
1012
0
        return NULL;
1013
0
    }
1014
1015
0
    if (self->fut_state != STATE_FINISHED) {
1016
0
        asyncio_state *state = get_asyncio_state_by_cls(cls);
1017
0
        PyErr_SetString(state->asyncio_InvalidStateError,
1018
0
                        "Exception is not set.");
1019
0
        return NULL;
1020
0
    }
1021
1022
0
    if (self->fut_exception != NULL) {
1023
0
        self->fut_log_tb = 0;
1024
0
        return Py_NewRef(self->fut_exception);
1025
0
    }
1026
1027
0
    Py_RETURN_NONE;
1028
0
}
1029
1030
/*[clinic input]
1031
@critical_section
1032
_asyncio.Future.set_result
1033
1034
    cls: defining_class
1035
    result: object
1036
    /
1037
1038
Mark the future done and set its result.
1039
1040
If the future is already done when this method is called, raises
1041
InvalidStateError.
1042
[clinic start generated code]*/
1043
1044
static PyObject *
1045
_asyncio_Future_set_result_impl(FutureObj *self, PyTypeObject *cls,
1046
                                PyObject *result)
1047
/*[clinic end generated code: output=99afbbe78f99c32d input=4069306f03a3b6ee]*/
1048
0
{
1049
0
    asyncio_state *state = get_asyncio_state_by_cls(cls);
1050
0
    ENSURE_FUTURE_ALIVE(state, self)
1051
0
    return future_set_result(state, self, result);
1052
0
}
1053
1054
/*[clinic input]
1055
@critical_section
1056
_asyncio.Future.set_exception
1057
1058
    cls: defining_class
1059
    exception: object
1060
    /
1061
1062
Mark the future done and set an exception.
1063
1064
If the future is already done when this method is called, raises
1065
InvalidStateError.
1066
[clinic start generated code]*/
1067
1068
static PyObject *
1069
_asyncio_Future_set_exception_impl(FutureObj *self, PyTypeObject *cls,
1070
                                   PyObject *exception)
1071
/*[clinic end generated code: output=0a5e8b5a52f058d6 input=b6eab43a389bc966]*/
1072
0
{
1073
0
    asyncio_state *state = get_asyncio_state_by_cls(cls);
1074
0
    ENSURE_FUTURE_ALIVE(state, self)
1075
0
    return future_set_exception(state, self, exception);
1076
0
}
1077
1078
/*[clinic input]
1079
@critical_section
1080
_asyncio.Future.add_done_callback
1081
1082
    cls: defining_class
1083
    fn: object
1084
    /
1085
    *
1086
    context: object = NULL
1087
1088
Add a callback to be run when the future becomes done.
1089
1090
The callback is called with a single argument - the future object.
1091
If the future is already done when this is called, the callback is
1092
scheduled with call_soon.
1093
[clinic start generated code]*/
1094
1095
static PyObject *
1096
_asyncio_Future_add_done_callback_impl(FutureObj *self, PyTypeObject *cls,
1097
                                       PyObject *fn, PyObject *context)
1098
/*[clinic end generated code: output=922e9a4cbd601167 input=f4f6adb074cd3e0f]*/
1099
0
{
1100
0
    asyncio_state *state = get_asyncio_state_by_cls(cls);
1101
0
    if (context == NULL) {
1102
0
        context = PyContext_CopyCurrent();
1103
0
        if (context == NULL) {
1104
0
            return NULL;
1105
0
        }
1106
0
        PyObject *res = future_add_done_callback(state, self, fn, context);
1107
0
        Py_DECREF(context);
1108
0
        return res;
1109
0
    }
1110
0
    return future_add_done_callback(state, self, fn, context);
1111
0
}
1112
1113
/*[clinic input]
1114
@critical_section
1115
_asyncio.Future.remove_done_callback
1116
1117
    cls: defining_class
1118
    fn: object
1119
    /
1120
1121
Remove all instances of a callback from the "call when done" list.
1122
1123
Returns the number of callbacks removed.
1124
[clinic start generated code]*/
1125
1126
static PyObject *
1127
_asyncio_Future_remove_done_callback_impl(FutureObj *self, PyTypeObject *cls,
1128
                                          PyObject *fn)
1129
/*[clinic end generated code: output=2da35ccabfe41b98 input=3afbc9f6a673091b]*/
1130
0
{
1131
0
    PyObject *newlist;
1132
0
    Py_ssize_t len, i, j=0;
1133
0
    Py_ssize_t cleared_callback0 = 0;
1134
1135
0
    asyncio_state *state = get_asyncio_state_by_cls(cls);
1136
0
    ENSURE_FUTURE_ALIVE(state, self)
1137
1138
0
    if (self->fut_callback0 != NULL) {
1139
        // Beware: An evil PyObject_RichCompareBool could free fut_callback0
1140
        // before a recursive call is made with that same arg. For details, see
1141
        // https://github.com/python/cpython/pull/125967#discussion_r1816593340.
1142
0
        PyObject *fut_callback0 = Py_NewRef(self->fut_callback0);
1143
0
        int cmp = PyObject_RichCompareBool(fut_callback0, fn, Py_EQ);
1144
0
        Py_DECREF(fut_callback0);
1145
0
        if (cmp == -1) {
1146
0
            return NULL;
1147
0
        }
1148
0
        if (cmp == 1) {
1149
            /* callback0 == fn */
1150
0
            Py_CLEAR(self->fut_callback0);
1151
0
            Py_CLEAR(self->fut_context0);
1152
0
            cleared_callback0 = 1;
1153
0
        }
1154
0
    }
1155
1156
0
    if (self->fut_callbacks == NULL) {
1157
0
        return PyLong_FromSsize_t(cleared_callback0);
1158
0
    }
1159
1160
0
    len = PyList_GET_SIZE(self->fut_callbacks);
1161
0
    if (len == 0) {
1162
0
        Py_CLEAR(self->fut_callbacks);
1163
0
        return PyLong_FromSsize_t(cleared_callback0);
1164
0
    }
1165
1166
0
    if (len == 1) {
1167
0
        PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
1168
0
        Py_INCREF(cb_tup);
1169
0
        int cmp = PyObject_RichCompareBool(
1170
0
            PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ);
1171
0
        Py_DECREF(cb_tup);
1172
0
        if (cmp == -1) {
1173
0
            return NULL;
1174
0
        }
1175
0
        if (cmp == 1) {
1176
            /* callbacks[0] == fn */
1177
0
            Py_CLEAR(self->fut_callbacks);
1178
0
            return PyLong_FromSsize_t(1 + cleared_callback0);
1179
0
        }
1180
        /* callbacks[0] != fn and len(callbacks) == 1 */
1181
0
        return PyLong_FromSsize_t(cleared_callback0);
1182
0
    }
1183
1184
0
    newlist = PyList_New(len);
1185
0
    if (newlist == NULL) {
1186
0
        return NULL;
1187
0
    }
1188
1189
    // Beware: PyObject_RichCompareBool below may change fut_callbacks.
1190
    // See GH-97592.
1191
0
    for (i = 0;
1192
0
         self->fut_callbacks != NULL && i < PyList_GET_SIZE(self->fut_callbacks);
1193
0
         i++) {
1194
0
        int ret;
1195
0
        PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
1196
0
        Py_INCREF(item);
1197
0
        ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ);
1198
0
        if (ret == 0) {
1199
0
            if (j < len) {
1200
0
                PyList_SET_ITEM(newlist, j, item);
1201
0
                j++;
1202
0
                continue;
1203
0
            }
1204
0
            ret = PyList_Append(newlist, item);
1205
0
        }
1206
0
        Py_DECREF(item);
1207
0
        if (ret < 0) {
1208
0
            goto fail;
1209
0
        }
1210
0
    }
1211
1212
    // Note: fut_callbacks may have been cleared.
1213
0
    if (j == 0 || self->fut_callbacks == NULL) {
1214
0
        Py_CLEAR(self->fut_callbacks);
1215
0
        Py_DECREF(newlist);
1216
0
        return PyLong_FromSsize_t(len + cleared_callback0);
1217
0
    }
1218
1219
0
    if (j < len) {
1220
0
        Py_SET_SIZE(newlist, j);
1221
0
    }
1222
0
    j = PyList_GET_SIZE(newlist);
1223
0
    len = PyList_GET_SIZE(self->fut_callbacks);
1224
0
    if (j != len) {
1225
0
        if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1226
0
            goto fail;
1227
0
        }
1228
0
    }
1229
0
    Py_DECREF(newlist);
1230
0
    return PyLong_FromSsize_t(len - j + cleared_callback0);
1231
1232
0
fail:
1233
0
    Py_DECREF(newlist);
1234
0
    return NULL;
1235
0
}
1236
1237
/*[clinic input]
1238
@critical_section
1239
_asyncio.Future.cancel
1240
1241
    cls: defining_class
1242
    /
1243
    msg: object = None
1244
1245
Cancel the future and schedule callbacks.
1246
1247
If the future is already done or cancelled, return False.
1248
Otherwise, change the future's state to cancelled, schedule the
1249
callbacks and return True.
1250
[clinic start generated code]*/
1251
1252
static PyObject *
1253
_asyncio_Future_cancel_impl(FutureObj *self, PyTypeObject *cls,
1254
                            PyObject *msg)
1255
/*[clinic end generated code: output=074956f35904b034 input=0c9157547a964c4c]*/
1256
0
{
1257
0
    asyncio_state *state = get_asyncio_state_by_cls(cls);
1258
0
    ENSURE_FUTURE_ALIVE(state, self)
1259
0
    return future_cancel(state, self, msg);
1260
0
}
1261
1262
/*[clinic input]
1263
@critical_section
1264
_asyncio.Future.cancelled
1265
1266
Return True if the future was cancelled.
1267
[clinic start generated code]*/
1268
1269
static PyObject *
1270
_asyncio_Future_cancelled_impl(FutureObj *self)
1271
/*[clinic end generated code: output=145197ced586357d input=9b8644819a675416]*/
1272
0
{
1273
0
    if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
1274
0
        Py_RETURN_TRUE;
1275
0
    }
1276
0
    else {
1277
0
        Py_RETURN_FALSE;
1278
0
    }
1279
0
}
1280
1281
/*[clinic input]
1282
@critical_section
1283
_asyncio.Future.done
1284
1285
Return True if the future is done.
1286
1287
Done means either that a result / exception are available, or that
1288
the future was cancelled.
1289
[clinic start generated code]*/
1290
1291
static PyObject *
1292
_asyncio_Future_done_impl(FutureObj *self)
1293
/*[clinic end generated code: output=244c5ac351145096 input=acf2c2347f3c01d8]*/
1294
0
{
1295
0
    if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
1296
0
        Py_RETURN_FALSE;
1297
0
    }
1298
0
    else {
1299
0
        Py_RETURN_TRUE;
1300
0
    }
1301
0
}
1302
1303
/*[clinic input]
1304
@critical_section
1305
_asyncio.Future.get_loop
1306
1307
    cls: defining_class
1308
    /
1309
1310
Return the event loop the Future is bound to.
1311
[clinic start generated code]*/
1312
1313
static PyObject *
1314
_asyncio_Future_get_loop_impl(FutureObj *self, PyTypeObject *cls)
1315
/*[clinic end generated code: output=f50ea6c374d9ee97 input=f3ce629bfd9f45c1]*/
1316
0
{
1317
0
    asyncio_state *state = get_asyncio_state_by_cls(cls);
1318
0
    ENSURE_FUTURE_ALIVE(state, self)
1319
0
    return Py_NewRef(self->fut_loop);
1320
0
}
1321
1322
/*[clinic input]
1323
@critical_section
1324
@getter
1325
_asyncio.Future._asyncio_awaited_by
1326
[clinic start generated code]*/
1327
1328
static PyObject *
1329
_asyncio_Future__asyncio_awaited_by_get_impl(FutureObj *self)
1330
/*[clinic end generated code: output=932af76d385d2e2a input=64c1783df2d44d2b]*/
1331
0
{
1332
    /* Implementation of a Python getter. */
1333
0
    if (self->fut_awaited_by == NULL) {
1334
0
        Py_RETURN_NONE;
1335
0
    }
1336
0
    if (self->fut_awaited_by_is_set) {
1337
        /* Already a set, just wrap it into a frozen set and return. */
1338
0
        assert(PySet_CheckExact(self->fut_awaited_by));
1339
0
        return PyFrozenSet_New(self->fut_awaited_by);
1340
0
    }
1341
1342
0
    PyObject *set = PyFrozenSet_New(NULL);
1343
0
    if (set == NULL) {
1344
0
        return NULL;
1345
0
    }
1346
0
    if (PySet_Add(set, self->fut_awaited_by)) {
1347
0
        Py_DECREF(set);
1348
0
        return NULL;
1349
0
    }
1350
0
    return set;
1351
0
}
1352
1353
1354
/*[clinic input]
1355
@critical_section
1356
@getter
1357
_asyncio.Future._asyncio_future_blocking -> bool
1358
[clinic start generated code]*/
1359
1360
static int
1361
_asyncio_Future__asyncio_future_blocking_get_impl(FutureObj *self)
1362
/*[clinic end generated code: output=32944de3df031979 input=2a51a0cf31a96826]*/
1363
0
{
1364
0
    return future_is_alive(self) && self->fut_blocking;
1365
0
}
1366
1367
/*[clinic input]
1368
@critical_section
1369
@setter
1370
_asyncio.Future._asyncio_future_blocking
1371
    value: bool
1372
[clinic start generated code]*/
1373
1374
static int
1375
_asyncio_Future__asyncio_future_blocking_set_impl(FutureObj *self, int value)
1376
/*[clinic end generated code: output=be2d5cb1cad6dd30 input=81780cb7b89f28e1]*/
1377
0
{
1378
0
    if (future_ensure_alive(self)) {
1379
0
        return -1;
1380
0
    }
1381
0
    self->fut_blocking = value;
1382
0
    return 0;
1383
0
}
1384
1385
/*[clinic input]
1386
@critical_section
1387
@getter
1388
_asyncio.Future._log_traceback -> bool
1389
[clinic start generated code]*/
1390
1391
static int
1392
_asyncio_Future__log_traceback_get_impl(FutureObj *self)
1393
/*[clinic end generated code: output=ba1356634182ac25 input=50f4db8eca9d1fb4]*/
1394
0
{
1395
0
    if (future_ensure_alive(self)) {
1396
0
        return -1;
1397
0
    }
1398
0
    return self->fut_log_tb;
1399
0
}
1400
1401
/*[clinic input]
1402
@critical_section
1403
@setter
1404
_asyncio.Future._log_traceback
1405
    value: bool
1406
[clinic start generated code]*/
1407
1408
static int
1409
_asyncio_Future__log_traceback_set_impl(FutureObj *self, int value)
1410
/*[clinic end generated code: output=ad84ae67ef80e3ad input=30c0f841c945c73f]*/
1411
0
{
1412
0
    if (value) {
1413
0
        PyErr_SetString(PyExc_ValueError,
1414
0
                        "_log_traceback can only be set to False");
1415
0
        return -1;
1416
0
    }
1417
0
    self->fut_log_tb = value;
1418
0
    return 0;
1419
0
}
1420
/*[clinic input]
1421
@critical_section
1422
@getter
1423
_asyncio.Future._loop
1424
[clinic start generated code]*/
1425
1426
static PyObject *
1427
_asyncio_Future__loop_get_impl(FutureObj *self)
1428
/*[clinic end generated code: output=5ba31563eecfeedf input=0337130bc5781670]*/
1429
0
{
1430
0
    if (!future_is_alive(self)) {
1431
0
        Py_RETURN_NONE;
1432
0
    }
1433
0
    return Py_NewRef(self->fut_loop);
1434
0
}
1435
1436
/*[clinic input]
1437
@critical_section
1438
@getter
1439
_asyncio.Future._callbacks
1440
[clinic start generated code]*/
1441
1442
static PyObject *
1443
_asyncio_Future__callbacks_get_impl(FutureObj *self)
1444
/*[clinic end generated code: output=b40d360505fcc583 input=7a466649530c01bb]*/
1445
0
{
1446
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
1447
0
    ENSURE_FUTURE_ALIVE(state, self)
1448
1449
0
    Py_ssize_t len = 0;
1450
0
    if (self->fut_callback0 != NULL) {
1451
0
        len++;
1452
0
    }
1453
0
    if (self->fut_callbacks != NULL) {
1454
0
        len += PyList_GET_SIZE(self->fut_callbacks);
1455
0
    }
1456
1457
0
    if (len == 0) {
1458
0
        Py_RETURN_NONE;
1459
0
    }
1460
1461
0
    PyObject *callbacks = PyList_New(len);
1462
0
    if (callbacks == NULL) {
1463
0
        return NULL;
1464
0
    }
1465
1466
0
    Py_ssize_t i = 0;
1467
0
    if (self->fut_callback0 != NULL) {
1468
0
        assert(self->fut_context0 != NULL);
1469
0
        PyObject *tup0 = _PyTuple_FromPair(self->fut_callback0, self->fut_context0);
1470
0
        if (tup0 == NULL) {
1471
0
            Py_DECREF(callbacks);
1472
0
            return NULL;
1473
0
        }
1474
0
        PyList_SET_ITEM(callbacks, i, tup0);
1475
0
        i++;
1476
0
    }
1477
1478
0
    if (self->fut_callbacks != NULL) {
1479
0
        for (Py_ssize_t j = 0; j < PyList_GET_SIZE(self->fut_callbacks); j++) {
1480
0
            PyObject *cb = PyList_GET_ITEM(self->fut_callbacks, j);
1481
0
            Py_INCREF(cb);
1482
0
            PyList_SET_ITEM(callbacks, i, cb);
1483
0
            i++;
1484
0
        }
1485
0
    }
1486
1487
0
    return callbacks;
1488
0
}
1489
1490
/*[clinic input]
1491
@critical_section
1492
@getter
1493
_asyncio.Future._result
1494
[clinic start generated code]*/
1495
1496
static PyObject *
1497
_asyncio_Future__result_get_impl(FutureObj *self)
1498
/*[clinic end generated code: output=6877e8ce97333873 input=624f8e28e67f2636]*/
1499
1500
0
{
1501
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
1502
0
    ENSURE_FUTURE_ALIVE(state, self)
1503
0
    if (self->fut_result == NULL) {
1504
0
        Py_RETURN_NONE;
1505
0
    }
1506
0
    return Py_NewRef(self->fut_result);
1507
0
}
1508
1509
/*[clinic input]
1510
@critical_section
1511
@getter
1512
_asyncio.Future._exception
1513
[clinic start generated code]*/
1514
1515
static PyObject *
1516
_asyncio_Future__exception_get_impl(FutureObj *self)
1517
/*[clinic end generated code: output=32f2c93b9e021a9b input=1828a1fcac929710]*/
1518
0
{
1519
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
1520
0
    ENSURE_FUTURE_ALIVE(state, self)
1521
0
    if (self->fut_exception == NULL) {
1522
0
        Py_RETURN_NONE;
1523
0
    }
1524
0
    return Py_NewRef(self->fut_exception);
1525
0
}
1526
1527
/*[clinic input]
1528
@critical_section
1529
@getter
1530
_asyncio.Future._source_traceback
1531
[clinic start generated code]*/
1532
1533
static PyObject *
1534
_asyncio_Future__source_traceback_get_impl(FutureObj *self)
1535
/*[clinic end generated code: output=d4f12b09af22f61b input=3c831fbde5da90d0]*/
1536
0
{
1537
0
    if (!future_is_alive(self) || self->fut_source_tb == NULL) {
1538
0
        Py_RETURN_NONE;
1539
0
    }
1540
0
    return Py_NewRef(self->fut_source_tb);
1541
0
}
1542
1543
/*[clinic input]
1544
@critical_section
1545
@getter
1546
_asyncio.Future._cancel_message
1547
[clinic start generated code]*/
1548
1549
static PyObject *
1550
_asyncio_Future__cancel_message_get_impl(FutureObj *self)
1551
/*[clinic end generated code: output=52ef6444f92cedac input=54c12c67082e4eea]*/
1552
0
{
1553
0
    if (self->fut_cancel_msg == NULL) {
1554
0
        Py_RETURN_NONE;
1555
0
    }
1556
0
    return Py_NewRef(self->fut_cancel_msg);
1557
0
}
1558
1559
/*[clinic input]
1560
@critical_section
1561
@setter
1562
_asyncio.Future._cancel_message
1563
[clinic start generated code]*/
1564
1565
static int
1566
_asyncio_Future__cancel_message_set_impl(FutureObj *self, PyObject *value)
1567
/*[clinic end generated code: output=0854b2f77bff2209 input=f461d17f2d891fad]*/
1568
0
{
1569
0
    Py_INCREF(value);
1570
0
    Py_XSETREF(self->fut_cancel_msg, value);
1571
0
    return 0;
1572
0
}
1573
1574
/*[clinic input]
1575
@critical_section
1576
@getter
1577
_asyncio.Future._state
1578
[clinic start generated code]*/
1579
1580
static PyObject *
1581
_asyncio_Future__state_get_impl(FutureObj *self)
1582
/*[clinic end generated code: output=622f560a3fa69c63 input=7c5ad023a93423ff]*/
1583
0
{
1584
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
1585
0
    PyObject *ret = NULL;
1586
1587
0
    ENSURE_FUTURE_ALIVE(state, self)
1588
1589
0
    switch (self->fut_state) {
1590
0
    case STATE_PENDING:
1591
0
        ret = &_Py_ID(PENDING);
1592
0
        break;
1593
0
    case STATE_CANCELLED:
1594
0
        ret = &_Py_ID(CANCELLED);
1595
0
        break;
1596
0
    case STATE_FINISHED:
1597
0
        ret = &_Py_ID(FINISHED);
1598
0
        break;
1599
0
    default:
1600
0
        assert (0);
1601
0
    }
1602
0
    assert(_Py_IsImmortal(ret));
1603
0
    return ret;
1604
0
}
1605
1606
static PyObject *
1607
FutureObj_repr(PyObject *op)
1608
0
{
1609
0
    FutureObj *fut = (FutureObj*)op;
1610
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
1611
0
    ENSURE_FUTURE_ALIVE(state, fut)
1612
0
    return PyObject_CallOneArg(state->asyncio_future_repr_func, (PyObject *)fut);
1613
0
}
1614
1615
/*[clinic input]
1616
@critical_section
1617
_asyncio.Future._make_cancelled_error
1618
1619
Create the CancelledError to raise if the Future is cancelled.
1620
1621
This should only be called once when handling a cancellation since
1622
it erases the context exception value.
1623
[clinic start generated code]*/
1624
1625
static PyObject *
1626
_asyncio_Future__make_cancelled_error_impl(FutureObj *self)
1627
/*[clinic end generated code: output=a5df276f6c1213de input=ccb90df8c3c18bcd]*/
1628
0
{
1629
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
1630
0
    return create_cancelled_error(state, self);
1631
0
}
1632
1633
static void
1634
FutureObj_finalize(PyObject *op)
1635
0
{
1636
0
    FutureObj *fut = (FutureObj*)op;
1637
0
    PyObject *context;
1638
0
    PyObject *message = NULL;
1639
0
    PyObject *func;
1640
1641
0
    if (!fut->fut_log_tb) {
1642
0
        return;
1643
0
    }
1644
0
    assert(fut->fut_exception != NULL);
1645
0
    fut->fut_log_tb = 0;
1646
1647
    /* Save the current exception, if any. */
1648
0
    PyObject *exc = PyErr_GetRaisedException();
1649
1650
0
    context = PyDict_New();
1651
0
    if (context == NULL) {
1652
0
        goto finally;
1653
0
    }
1654
1655
0
    message = PyUnicode_FromFormat(
1656
0
        "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
1657
0
    if (message == NULL) {
1658
0
        goto finally;
1659
0
    }
1660
1661
0
    if (PyDict_SetItem(context, &_Py_ID(message), message) < 0 ||
1662
0
        PyDict_SetItem(context, &_Py_ID(exception), fut->fut_exception) < 0 ||
1663
0
        PyDict_SetItem(context, &_Py_ID(future), (PyObject*)fut) < 0) {
1664
0
        goto finally;
1665
0
    }
1666
0
    if (fut->fut_source_tb != NULL) {
1667
0
        if (PyDict_SetItem(context, &_Py_ID(source_traceback),
1668
0
                              fut->fut_source_tb) < 0) {
1669
0
            goto finally;
1670
0
        }
1671
0
    }
1672
1673
0
    func = PyObject_GetAttr(fut->fut_loop, &_Py_ID(call_exception_handler));
1674
0
    if (func != NULL) {
1675
0
        PyObject *res = PyObject_CallOneArg(func, context);
1676
0
        if (res == NULL) {
1677
0
            PyErr_FormatUnraisable("Exception ignored while calling asyncio "
1678
0
                                   "function %R", func);
1679
0
        }
1680
0
        else {
1681
0
            Py_DECREF(res);
1682
0
        }
1683
0
        Py_DECREF(func);
1684
0
    }
1685
1686
0
finally:
1687
0
    Py_XDECREF(context);
1688
0
    Py_XDECREF(message);
1689
1690
    /* Restore the saved exception. */
1691
0
    PyErr_SetRaisedException(exc);
1692
0
}
1693
1694
static PyMethodDef FutureType_methods[] = {
1695
    _ASYNCIO_FUTURE_RESULT_METHODDEF
1696
    _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1697
    _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1698
    _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1699
    _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1700
    _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1701
    _ASYNCIO_FUTURE_CANCEL_METHODDEF
1702
    _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1703
    _ASYNCIO_FUTURE_DONE_METHODDEF
1704
    _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
1705
    _ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF
1706
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS,
1707
    PyDoc_STR("Futures are generic over the type of their results")},
1708
    {NULL, NULL}        /* Sentinel */
1709
};
1710
1711
static PyGetSetDef FutureType_getsetlist[] = {
1712
    _ASYNCIO_FUTURE__STATE_GETSETDEF
1713
    _ASYNCIO_FUTURE__ASYNCIO_FUTURE_BLOCKING_GETSETDEF
1714
    _ASYNCIO_FUTURE__LOOP_GETSETDEF
1715
    _ASYNCIO_FUTURE__CALLBACKS_GETSETDEF
1716
    _ASYNCIO_FUTURE__RESULT_GETSETDEF
1717
    _ASYNCIO_FUTURE__EXCEPTION_GETSETDEF
1718
    _ASYNCIO_FUTURE__LOG_TRACEBACK_GETSETDEF
1719
    _ASYNCIO_FUTURE__SOURCE_TRACEBACK_GETSETDEF
1720
    _ASYNCIO_FUTURE__CANCEL_MESSAGE_GETSETDEF
1721
    _ASYNCIO_FUTURE__ASYNCIO_AWAITED_BY_GETSETDEF
1722
    {NULL} /* Sentinel */
1723
};
1724
1725
static void FutureObj_dealloc(PyObject *self);
1726
1727
static PyType_Slot Future_slots[] = {
1728
    {Py_tp_dealloc, FutureObj_dealloc},
1729
    {Py_tp_repr, FutureObj_repr},
1730
    {Py_tp_doc, (void *)_asyncio_Future___init____doc__},
1731
    {Py_tp_traverse, FutureObj_traverse},
1732
    {Py_tp_clear, FutureObj_clear},
1733
    {Py_tp_iter, future_new_iter},
1734
    {Py_tp_methods, FutureType_methods},
1735
    {Py_tp_getset, FutureType_getsetlist},
1736
    {Py_tp_init, _asyncio_Future___init__},
1737
    {Py_tp_new, PyType_GenericNew},
1738
    {Py_tp_finalize, FutureObj_finalize},
1739
1740
    // async slots
1741
    {Py_am_await, future_new_iter},
1742
    {0, NULL},
1743
};
1744
1745
static PyType_Spec Future_spec = {
1746
    .name = "_asyncio.Future",
1747
    .basicsize = sizeof(FutureObj),
1748
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
1749
              Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT |
1750
              Py_TPFLAGS_MANAGED_WEAKREF),
1751
    .slots = Future_slots,
1752
};
1753
1754
static void
1755
FutureObj_dealloc(PyObject *self)
1756
0
{
1757
0
    if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1758
        // resurrected.
1759
0
        return;
1760
0
    }
1761
1762
0
    PyTypeObject *tp = Py_TYPE(self);
1763
0
    PyObject_GC_UnTrack(self);
1764
1765
0
    PyObject_ClearWeakRefs(self);
1766
1767
0
    (void)FutureObj_clear(self);
1768
0
    tp->tp_free(self);
1769
0
    Py_DECREF(tp);
1770
0
}
1771
1772
1773
/*********************** Future Iterator **************************/
1774
1775
typedef struct futureiterobject {
1776
    PyObject_HEAD
1777
    FutureObj *future;
1778
} futureiterobject;
1779
1780
1781
static void
1782
FutureIter_dealloc(PyObject *it)
1783
0
{
1784
0
    PyTypeObject *tp = Py_TYPE(it);
1785
1786
0
    assert(_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE));
1787
1788
0
    PyObject_GC_UnTrack(it);
1789
0
    tp->tp_clear(it);
1790
1791
0
    if (!_Py_FREELIST_PUSH(futureiters, it, Py_futureiters_MAXFREELIST)) {
1792
0
        PyObject_GC_Del(it);
1793
0
        Py_DECREF(tp);
1794
0
    }
1795
0
}
1796
1797
static PySendResult
1798
FutureIter_am_send_lock_held(futureiterobject *it, PyObject **result)
1799
0
{
1800
0
    PyObject *res;
1801
0
    FutureObj *fut = it->future;
1802
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
1803
1804
0
    *result = NULL;
1805
1806
0
    if (fut->fut_state == STATE_PENDING) {
1807
0
        if (!fut->fut_blocking) {
1808
0
            fut->fut_blocking = 1;
1809
0
            *result = Py_NewRef(fut);
1810
0
            return PYGEN_NEXT;
1811
0
        }
1812
0
        PyErr_SetString(PyExc_RuntimeError,
1813
0
                        "await wasn't used with future");
1814
0
        return PYGEN_ERROR;
1815
0
    }
1816
1817
0
    res = _asyncio_Future_result_impl(fut);
1818
0
    if (res != NULL) {
1819
0
        *result = res;
1820
0
        return PYGEN_RETURN;
1821
0
    }
1822
1823
0
    return PYGEN_ERROR;
1824
0
}
1825
1826
static PySendResult
1827
FutureIter_am_send(PyObject *op,
1828
                   PyObject *Py_UNUSED(arg),
1829
                   PyObject **result)
1830
0
{
1831
0
    futureiterobject *it = (futureiterobject*)op;
1832
    /* arg is unused, see the comment on FutureIter_send for clarification */
1833
0
    PySendResult res;
1834
0
    Py_BEGIN_CRITICAL_SECTION(it->future);
1835
0
    res = FutureIter_am_send_lock_held(it, result);
1836
0
    Py_END_CRITICAL_SECTION();
1837
0
    return res;
1838
0
}
1839
1840
1841
static PyObject *
1842
FutureIter_iternext(PyObject *it)
1843
0
{
1844
0
    PyObject *result;
1845
0
    switch (FutureIter_am_send(it, Py_None, &result)) {
1846
0
        case PYGEN_RETURN:
1847
0
            (void)_PyGen_SetStopIterationValue(result);
1848
0
            Py_DECREF(result);
1849
0
            return NULL;
1850
0
        case PYGEN_NEXT:
1851
0
            return result;
1852
0
        case PYGEN_ERROR:
1853
0
            return NULL;
1854
0
        default:
1855
0
            Py_UNREACHABLE();
1856
0
    }
1857
0
}
1858
1859
static PyObject *
1860
FutureIter_send(PyObject *self, PyObject *unused)
1861
0
{
1862
    /* Future.__iter__ doesn't care about values that are pushed to the
1863
     * generator, it just returns self.result().
1864
     */
1865
0
    return FutureIter_iternext(self);
1866
0
}
1867
1868
static PyObject *
1869
FutureIter_throw(PyObject *op, PyObject *const *args, Py_ssize_t nargs)
1870
0
{
1871
0
    futureiterobject *self = (futureiterobject*)op;
1872
0
    PyObject *type, *val = NULL, *tb = NULL;
1873
0
    if (!_PyArg_CheckPositional("throw", nargs, 1, 3)) {
1874
0
        return NULL;
1875
0
    }
1876
0
    if (nargs > 1) {
1877
0
        if (PyErr_WarnEx(PyExc_DeprecationWarning,
1878
0
                            "the (type, exc, tb) signature of throw() is deprecated, "
1879
0
                            "use the single-arg signature instead.",
1880
0
                            1) < 0) {
1881
0
            return NULL;
1882
0
        }
1883
0
    }
1884
1885
0
    type = args[0];
1886
0
    if (nargs == 3) {
1887
0
        val = args[1];
1888
0
        tb = args[2];
1889
0
    }
1890
0
    else if (nargs == 2) {
1891
0
        val = args[1];
1892
0
    }
1893
1894
0
    if (val == Py_None) {
1895
0
        val = NULL;
1896
0
    }
1897
0
    if (tb == Py_None ) {
1898
0
        tb = NULL;
1899
0
    } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1900
0
        PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1901
0
        return NULL;
1902
0
    }
1903
1904
0
    Py_INCREF(type);
1905
0
    Py_XINCREF(val);
1906
0
    Py_XINCREF(tb);
1907
1908
0
    if (PyExceptionClass_Check(type)) {
1909
0
        PyErr_NormalizeException(&type, &val, &tb);
1910
        /* No need to call PyException_SetTraceback since we'll be calling
1911
           PyErr_Restore for `type`, `val`, and `tb`. */
1912
0
    } else if (PyExceptionInstance_Check(type)) {
1913
0
        if (val) {
1914
0
            PyErr_SetString(PyExc_TypeError,
1915
0
                            "instance exception may not have a separate value");
1916
0
            goto fail;
1917
0
        }
1918
0
        val = type;
1919
0
        type = PyExceptionInstance_Class(type);
1920
0
        Py_INCREF(type);
1921
0
        if (tb == NULL)
1922
0
            tb = PyException_GetTraceback(val);
1923
0
    } else {
1924
0
        PyErr_SetString(PyExc_TypeError,
1925
0
                        "exceptions must be classes deriving BaseException or "
1926
0
                        "instances of such a class");
1927
0
        goto fail;
1928
0
    }
1929
1930
0
    Py_CLEAR(self->future);
1931
1932
0
    PyErr_Restore(type, val, tb);
1933
1934
0
    return NULL;
1935
1936
0
  fail:
1937
0
    Py_DECREF(type);
1938
0
    Py_XDECREF(val);
1939
0
    Py_XDECREF(tb);
1940
0
    return NULL;
1941
0
}
1942
1943
static int
1944
FutureIter_clear(PyObject *op)
1945
0
{
1946
0
    futureiterobject *it = (futureiterobject*)op;
1947
0
    Py_CLEAR(it->future);
1948
0
    return 0;
1949
0
}
1950
1951
static PyObject *
1952
FutureIter_close(PyObject *self, PyObject *arg)
1953
0
{
1954
0
    (void)FutureIter_clear(self);
1955
0
    Py_RETURN_NONE;
1956
0
}
1957
1958
static int
1959
FutureIter_traverse(PyObject *op, visitproc visit, void *arg)
1960
0
{
1961
0
    futureiterobject *it = (futureiterobject*)op;
1962
0
    Py_VISIT(Py_TYPE(it));
1963
0
    Py_VISIT(it->future);
1964
0
    return 0;
1965
0
}
1966
1967
static PyMethodDef FutureIter_methods[] = {
1968
    {"send",  FutureIter_send, METH_O, NULL},
1969
    {"throw", _PyCFunction_CAST(FutureIter_throw), METH_FASTCALL, NULL},
1970
    {"close", FutureIter_close, METH_NOARGS, NULL},
1971
    {NULL, NULL}        /* Sentinel */
1972
};
1973
1974
static PyType_Slot FutureIter_slots[] = {
1975
    {Py_tp_dealloc, FutureIter_dealloc},
1976
    {Py_tp_getattro, PyObject_GenericGetAttr},
1977
    {Py_tp_traverse, FutureIter_traverse},
1978
    {Py_tp_clear, FutureIter_clear},
1979
    {Py_tp_iter, PyObject_SelfIter},
1980
    {Py_tp_iternext, FutureIter_iternext},
1981
    {Py_tp_methods, FutureIter_methods},
1982
1983
    // async methods
1984
    {Py_am_send, FutureIter_am_send},
1985
    {0, NULL},
1986
};
1987
1988
static PyType_Spec FutureIter_spec = {
1989
    .name = "_asyncio.FutureIter",
1990
    .basicsize = sizeof(futureiterobject),
1991
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1992
              Py_TPFLAGS_IMMUTABLETYPE),
1993
    .slots = FutureIter_slots,
1994
};
1995
1996
static PyObject *
1997
future_new_iter(PyObject *fut)
1998
0
{
1999
0
    futureiterobject *it;
2000
2001
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
2002
0
    ENSURE_FUTURE_ALIVE(state, fut)
2003
2004
0
    it = _Py_FREELIST_POP(futureiterobject, futureiters);
2005
0
    if (it == NULL) {
2006
0
        it = PyObject_GC_New(futureiterobject, state->FutureIterType);
2007
0
        if (it == NULL) {
2008
0
            return NULL;
2009
0
        }
2010
0
    }
2011
2012
0
    it->future = (FutureObj*)Py_NewRef(fut);
2013
0
    PyObject_GC_Track(it);
2014
0
    return (PyObject*)it;
2015
0
}
2016
2017
2018
/*********************** Task **************************/
2019
2020
2021
/*[clinic input]
2022
class _asyncio.Task "TaskObj *" "&Task_Type"
2023
[clinic start generated code]*/
2024
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
2025
2026
static int task_call_step_soon(asyncio_state *state, TaskObj *, PyObject *);
2027
static PyObject *task_wakeup(PyObject *op, PyObject *arg);
2028
static PyObject *task_step(asyncio_state *, TaskObj *, PyObject *);
2029
static int task_eager_start(_PyThreadStateImpl *ts, asyncio_state *state, TaskObj *task);
2030
2031
/* ----- Task._step wrapper */
2032
2033
static int
2034
TaskStepMethWrapper_clear(PyObject *op)
2035
0
{
2036
0
    TaskStepMethWrapper *o = (TaskStepMethWrapper*)op;
2037
0
    Py_CLEAR(o->sw_task);
2038
0
    Py_CLEAR(o->sw_arg);
2039
0
    return 0;
2040
0
}
2041
2042
static void
2043
TaskStepMethWrapper_dealloc(PyObject *op)
2044
0
{
2045
0
    TaskStepMethWrapper *o = (TaskStepMethWrapper*)op;
2046
0
    PyTypeObject *tp = Py_TYPE(o);
2047
0
    PyObject_GC_UnTrack(o);
2048
0
    (void)TaskStepMethWrapper_clear(op);
2049
0
    Py_TYPE(o)->tp_free(o);
2050
0
    Py_DECREF(tp);
2051
0
}
2052
2053
static PyObject *
2054
TaskStepMethWrapper_call(PyObject *op,
2055
                         PyObject *args, PyObject *kwds)
2056
0
{
2057
0
    TaskStepMethWrapper *o = (TaskStepMethWrapper*)op;
2058
0
    if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
2059
0
        PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
2060
0
        return NULL;
2061
0
    }
2062
0
    if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
2063
0
        PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
2064
0
        return NULL;
2065
0
    }
2066
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)o);
2067
0
    PyObject *res;
2068
0
    Py_BEGIN_CRITICAL_SECTION(o->sw_task);
2069
0
    res = task_step(state, o->sw_task, o->sw_arg);
2070
0
    Py_END_CRITICAL_SECTION();
2071
0
    return res;
2072
0
}
2073
2074
static int
2075
TaskStepMethWrapper_traverse(PyObject *op,
2076
                             visitproc visit, void *arg)
2077
0
{
2078
0
    TaskStepMethWrapper *o = (TaskStepMethWrapper*)op;
2079
0
    Py_VISIT(Py_TYPE(o));
2080
0
    Py_VISIT(o->sw_task);
2081
0
    Py_VISIT(o->sw_arg);
2082
0
    return 0;
2083
0
}
2084
2085
static PyObject *
2086
TaskStepMethWrapper_get___self__(PyObject *op, void *Py_UNUSED(closure))
2087
0
{
2088
0
    TaskStepMethWrapper *o = (TaskStepMethWrapper*)op;
2089
0
    if (o->sw_task) {
2090
0
        return Py_NewRef(o->sw_task);
2091
0
    }
2092
0
    Py_RETURN_NONE;
2093
0
}
2094
2095
static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
2096
    {"__self__", TaskStepMethWrapper_get___self__, NULL, NULL},
2097
    {NULL} /* Sentinel */
2098
};
2099
2100
static PyType_Slot TaskStepMethWrapper_slots[] = {
2101
    {Py_tp_getset, TaskStepMethWrapper_getsetlist},
2102
    {Py_tp_dealloc, TaskStepMethWrapper_dealloc},
2103
    {Py_tp_call, TaskStepMethWrapper_call},
2104
    {Py_tp_getattro, PyObject_GenericGetAttr},
2105
    {Py_tp_traverse, TaskStepMethWrapper_traverse},
2106
    {Py_tp_clear, TaskStepMethWrapper_clear},
2107
    {0, NULL},
2108
};
2109
2110
static PyType_Spec TaskStepMethWrapper_spec = {
2111
    .name = "_asyncio.TaskStepMethWrapper",
2112
    .basicsize = sizeof(TaskStepMethWrapper),
2113
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2114
              Py_TPFLAGS_IMMUTABLETYPE),
2115
    .slots = TaskStepMethWrapper_slots,
2116
};
2117
2118
static PyObject *
2119
TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
2120
0
{
2121
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)task);
2122
0
    TaskStepMethWrapper *o;
2123
0
    o = PyObject_GC_New(TaskStepMethWrapper, state->TaskStepMethWrapper_Type);
2124
0
    if (o == NULL) {
2125
0
        return NULL;
2126
0
    }
2127
2128
0
    o->sw_task = (TaskObj*)Py_NewRef(task);
2129
0
    o->sw_arg = Py_XNewRef(arg);
2130
2131
0
    PyObject_GC_Track(o);
2132
0
    return (PyObject*) o;
2133
0
}
2134
2135
/* ----- Task._wakeup implementation */
2136
2137
static  PyMethodDef TaskWakeupDef = {
2138
    "task_wakeup",
2139
    task_wakeup,
2140
    METH_O,
2141
    NULL
2142
};
2143
2144
/* ----- Task introspection helpers */
2145
2146
static void
2147
register_task(_PyThreadStateImpl *ts, TaskObj *task)
2148
0
{
2149
0
    if (task->task_node.next != NULL) {
2150
        // already registered
2151
0
        assert(task->task_node.prev != NULL);
2152
0
        return;
2153
0
    }
2154
0
    struct llist_node *head = &ts->asyncio_tasks_head;
2155
0
    llist_insert_tail(head, &task->task_node);
2156
0
}
2157
2158
static inline void
2159
unregister_task_safe(TaskObj *task)
2160
0
{
2161
0
    if (task->task_node.next == NULL) {
2162
        // not registered
2163
0
        assert(task->task_node.prev == NULL);
2164
0
        return;
2165
0
    }
2166
0
    llist_remove(&task->task_node);
2167
0
}
2168
2169
static void
2170
unregister_task(TaskObj *task)
2171
0
{
2172
#ifdef Py_GIL_DISABLED
2173
    // check if we are in the same thread
2174
    // if so, we can avoid locking
2175
    if (task->task_tid == _Py_ThreadId()) {
2176
        unregister_task_safe(task);
2177
    }
2178
    else {
2179
        // we are in a different thread
2180
        // stop the world then check and remove the task
2181
        PyThreadState *tstate = _PyThreadState_GET();
2182
        _PyEval_StopTheWorld(tstate->interp);
2183
        unregister_task_safe(task);
2184
        _PyEval_StartTheWorld(tstate->interp);
2185
    }
2186
#else
2187
0
    unregister_task_safe(task);
2188
0
#endif
2189
0
}
2190
2191
static int
2192
enter_task(_PyThreadStateImpl *ts, PyObject *loop, PyObject *task)
2193
0
{
2194
0
    if (ts->asyncio_running_loop != loop) {
2195
0
        PyErr_Format(PyExc_RuntimeError, "loop %R is not the running loop", loop);
2196
0
        return -1;
2197
0
    }
2198
2199
0
    if (ts->asyncio_running_task != NULL) {
2200
0
        PyErr_Format(
2201
0
            PyExc_RuntimeError,
2202
0
            "Cannot enter into task %R while another " \
2203
0
            "task %R is being executed.",
2204
0
            task, ts->asyncio_running_task);
2205
0
        return -1;
2206
0
    }
2207
2208
0
    ts->asyncio_running_task = Py_NewRef(task);
2209
0
    return 0;
2210
0
}
2211
2212
static int
2213
leave_task(_PyThreadStateImpl *ts, PyObject *loop, PyObject *task)
2214
0
{
2215
0
    if (ts->asyncio_running_loop != loop) {
2216
0
        PyErr_Format(PyExc_RuntimeError, "loop %R is not the running loop", loop);
2217
0
        return -1;
2218
0
    }
2219
2220
0
    if (ts->asyncio_running_task != task) {
2221
0
        PyErr_Format(
2222
0
            PyExc_RuntimeError,
2223
0
            "Invalid attempt to leave task %R while " \
2224
0
            "task %R is entered.",
2225
0
            task, ts->asyncio_running_task ? ts->asyncio_running_task : Py_None);
2226
0
        return -1;
2227
0
    }
2228
0
    Py_CLEAR(ts->asyncio_running_task);
2229
0
    return 0;
2230
0
}
2231
2232
static PyObject *
2233
swap_current_task(_PyThreadStateImpl *ts, PyObject *loop, PyObject *task)
2234
0
{
2235
0
    if (ts->asyncio_running_loop != loop) {
2236
0
        PyErr_Format(PyExc_RuntimeError, "loop %R is not the running loop", loop);
2237
0
        return NULL;
2238
0
    }
2239
2240
    /* transfer ownership to avoid redundant ref counting */
2241
0
    PyObject *prev_task = ts->asyncio_running_task;
2242
0
    if (task != Py_None) {
2243
0
        ts->asyncio_running_task = Py_NewRef(task);
2244
0
    } else {
2245
0
        ts->asyncio_running_task = NULL;
2246
0
    }
2247
0
    if (prev_task == NULL) {
2248
0
        Py_RETURN_NONE;
2249
0
    }
2250
0
    return prev_task;
2251
0
}
2252
2253
/* ----- Task */
2254
2255
/*[clinic input]
2256
_asyncio.Task.__init__
2257
2258
    coro: object
2259
    *
2260
    loop: object = None
2261
    name: object = None
2262
    context: object = None
2263
    eager_start: bool = False
2264
2265
A coroutine wrapped in a Future.
2266
[clinic start generated code]*/
2267
2268
static int
2269
_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2270
                            PyObject *name, PyObject *context,
2271
                            int eager_start)
2272
/*[clinic end generated code: output=7aced2d27836f1a1 input=18e3f113a51b829d]*/
2273
0
{
2274
0
    if (future_init((FutureObj*)self, loop)) {
2275
0
        return -1;
2276
0
    }
2277
0
    self->task_is_task = 1;
2278
2279
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
2280
0
    int is_coro = is_coroutine(state, coro);
2281
0
    if (is_coro == -1) {
2282
0
        return -1;
2283
0
    }
2284
0
    if (is_coro == 0) {
2285
0
        self->task_log_destroy_pending = 0;
2286
0
        PyErr_Format(PyExc_TypeError,
2287
0
                     "a coroutine was expected, got %R",
2288
0
                     coro);
2289
0
        return -1;
2290
0
    }
2291
2292
0
    if (context == Py_None) {
2293
0
        Py_XSETREF(self->task_context, PyContext_CopyCurrent());
2294
0
        if (self->task_context == NULL) {
2295
0
            return -1;
2296
0
        }
2297
0
    } else if (!PyContext_CheckExact(context)) {
2298
        // gh-157301: the passed value must be a contextvars.Context
2299
0
        self->task_log_destroy_pending = 0;
2300
0
        PyErr_Format(PyExc_TypeError,
2301
0
                     "a contextvars.Context was expected, got %T",
2302
0
                     context);
2303
0
        return -1;
2304
0
    } else {
2305
0
        Py_XSETREF(self->task_context, Py_NewRef(context));
2306
0
    }
2307
2308
0
    Py_CLEAR(self->task_fut_waiter);
2309
#ifdef Py_GIL_DISABLED
2310
    self->task_tid = _Py_ThreadId();
2311
#endif
2312
0
    self->task_must_cancel = 0;
2313
0
    self->task_log_destroy_pending = 1;
2314
0
    self->task_num_cancels_requested = 0;
2315
0
    set_task_coro(self, coro);
2316
2317
0
    if (name == Py_None) {
2318
        // optimization: defer task name formatting
2319
        // store the task counter as PyLong in the name
2320
        // for deferred formatting in get_name
2321
#ifdef Py_GIL_DISABLED
2322
        unsigned long long counter = _Py_atomic_add_uint64(&state->task_name_counter, 1) + 1;
2323
#else
2324
0
        unsigned long long counter = ++state->task_name_counter;
2325
0
#endif
2326
0
        name = PyLong_FromUnsignedLongLong(counter);
2327
0
    } else if (!PyUnicode_CheckExact(name)) {
2328
0
        name = PyObject_Str(name);
2329
0
    } else {
2330
0
        Py_INCREF(name);
2331
0
    }
2332
0
    Py_XSETREF(self->task_name, name);
2333
0
    if (self->task_name == NULL) {
2334
0
        return -1;
2335
0
    }
2336
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
2337
#ifdef Py_GIL_DISABLED
2338
    // This is required so that _Py_TryIncref(self)
2339
    // works correctly in non-owning threads.
2340
    _PyObject_SetMaybeWeakref((PyObject *)self);
2341
#endif
2342
0
    if (eager_start) {
2343
        // gh-154695: loop may be None here, future_init() resolved it into task_loop.
2344
0
        PyObject *res = PyObject_CallMethodNoArgs(self->task_loop,
2345
0
                                                  &_Py_ID(is_running));
2346
0
        if (res == NULL) {
2347
0
            return -1;
2348
0
        }
2349
0
        int is_loop_running = Py_IsTrue(res);
2350
0
        Py_DECREF(res);
2351
0
        if (is_loop_running) {
2352
0
            if (task_eager_start(ts, state, self)) {
2353
0
                return -1;
2354
0
            }
2355
0
            return 0;
2356
0
        }
2357
0
    }
2358
2359
0
    if (task_call_step_soon(state, self, NULL)) {
2360
0
        return -1;
2361
0
    }
2362
0
    register_task(ts, self);
2363
0
    return 0;
2364
0
}
2365
2366
static int
2367
TaskObj_clear(PyObject *op)
2368
0
{
2369
0
    TaskObj *task = (TaskObj*)op;
2370
0
    (void)FutureObj_clear(op);
2371
0
    clear_task_coro(task);
2372
0
    Py_CLEAR(task->task_context);
2373
0
    Py_CLEAR(task->task_name);
2374
0
    Py_CLEAR(task->task_fut_waiter);
2375
0
    return 0;
2376
0
}
2377
2378
static int
2379
TaskObj_traverse(PyObject *op, visitproc visit, void *arg)
2380
0
{
2381
0
    TaskObj *task = (TaskObj*)op;
2382
0
    Py_VISIT(Py_TYPE(task));
2383
0
    Py_VISIT(task->task_context);
2384
0
    Py_VISIT(task->task_coro);
2385
0
    Py_VISIT(task->task_name);
2386
0
    Py_VISIT(task->task_fut_waiter);
2387
0
    FutureObj *fut = (FutureObj *)task;
2388
0
    Py_VISIT(fut->fut_loop);
2389
0
    Py_VISIT(fut->fut_callback0);
2390
0
    Py_VISIT(fut->fut_context0);
2391
0
    Py_VISIT(fut->fut_callbacks);
2392
0
    Py_VISIT(fut->fut_result);
2393
0
    Py_VISIT(fut->fut_exception);
2394
0
    Py_VISIT(fut->fut_exception_tb);
2395
0
    Py_VISIT(fut->fut_source_tb);
2396
0
    Py_VISIT(fut->fut_cancel_msg);
2397
0
    Py_VISIT(fut->fut_cancelled_exc);
2398
0
    Py_VISIT(fut->fut_awaited_by);
2399
0
    return PyObject_VisitManagedDict((PyObject *)fut, visit, arg);
2400
0
}
2401
2402
/*[clinic input]
2403
@critical_section
2404
@getter
2405
_asyncio.Task._log_destroy_pending -> bool
2406
[clinic start generated code]*/
2407
2408
static int
2409
_asyncio_Task__log_destroy_pending_get_impl(TaskObj *self)
2410
/*[clinic end generated code: output=98b5f7bad24a2381 input=a87002bdf72e380b]*/
2411
0
{
2412
0
    return self->task_log_destroy_pending;
2413
0
}
2414
2415
/*[clinic input]
2416
@critical_section
2417
@setter
2418
_asyncio.Task._log_destroy_pending
2419
    value: bool
2420
[clinic start generated code]*/
2421
2422
static int
2423
_asyncio_Task__log_destroy_pending_set_impl(TaskObj *self, int value)
2424
/*[clinic end generated code: output=132bbf2b4c627777 input=533fea7776daa075]*/
2425
0
{
2426
0
    self->task_log_destroy_pending = value;
2427
0
    return 0;
2428
0
}
2429
2430
2431
/*[clinic input]
2432
@critical_section
2433
@getter
2434
_asyncio.Task._must_cancel
2435
[clinic start generated code]*/
2436
2437
static PyObject *
2438
_asyncio_Task__must_cancel_get_impl(TaskObj *self)
2439
/*[clinic end generated code: output=70e79b900996c363 input=2d04529fb23feedf]*/
2440
0
{
2441
0
    if (self->task_must_cancel) {
2442
0
        Py_RETURN_TRUE;
2443
0
    }
2444
0
    else {
2445
0
        Py_RETURN_FALSE;
2446
0
    }
2447
0
}
2448
2449
/*[clinic input]
2450
@critical_section
2451
@getter
2452
_asyncio.Task._coro
2453
[clinic start generated code]*/
2454
2455
static PyObject *
2456
_asyncio_Task__coro_get_impl(TaskObj *self)
2457
/*[clinic end generated code: output=a2726012ab5fd531 input=323c31a272020624]*/
2458
0
{
2459
0
    if (self->task_coro) {
2460
0
        return Py_NewRef(self->task_coro);
2461
0
    }
2462
2463
0
    Py_RETURN_NONE;
2464
0
}
2465
2466
2467
/*[clinic input]
2468
@critical_section
2469
@getter
2470
_asyncio.Task._fut_waiter
2471
[clinic start generated code]*/
2472
2473
static PyObject *
2474
_asyncio_Task__fut_waiter_get_impl(TaskObj *self)
2475
/*[clinic end generated code: output=c4f966b847fefcdf input=4d1005d725e72db7]*/
2476
0
{
2477
0
    if (self->task_fut_waiter) {
2478
0
        return Py_NewRef(self->task_fut_waiter);
2479
0
    }
2480
2481
0
    Py_RETURN_NONE;
2482
0
}
2483
2484
static PyObject *
2485
TaskObj_repr(PyObject *task)
2486
0
{
2487
0
    asyncio_state *state = get_asyncio_state_by_def(task);
2488
0
    return PyObject_CallOneArg(state->asyncio_task_repr_func, task);
2489
0
}
2490
2491
2492
/*[clinic input]
2493
@critical_section
2494
_asyncio.Task._make_cancelled_error
2495
2496
Create the CancelledError to raise if the Task is cancelled.
2497
2498
This should only be called once when handling a cancellation since
2499
it erases the context exception value.
2500
[clinic start generated code]*/
2501
2502
static PyObject *
2503
_asyncio_Task__make_cancelled_error_impl(TaskObj *self)
2504
/*[clinic end generated code: output=55a819e8b4276fab input=2d3213be0cb02390]*/
2505
0
{
2506
0
    FutureObj *fut = (FutureObj*)self;
2507
0
    return _asyncio_Future__make_cancelled_error_impl(fut);
2508
0
}
2509
2510
2511
/*[clinic input]
2512
@critical_section
2513
_asyncio.Task.cancel
2514
2515
    msg: object = None
2516
2517
Request that this task cancel itself.
2518
2519
This arranges for a CancelledError to be thrown into the
2520
wrapped coroutine on the next cycle through the event loop.
2521
The coroutine then has a chance to clean up or even deny
2522
the request using try/except/finally.
2523
2524
Unlike Future.cancel, this does not guarantee that the
2525
task will be cancelled: the exception might be caught and
2526
acted upon, delaying cancellation of the task or preventing
2527
cancellation completely.  The task may also return a value or
2528
raise a different exception.
2529
2530
Immediately after this method is called, Task.cancelled() will
2531
not return True (unless the task was already cancelled).  A
2532
task will be marked as cancelled when the wrapped coroutine
2533
terminates with a CancelledError exception (even if cancel()
2534
was not called).
2535
2536
This also increases the task's count of cancellation requests.
2537
[clinic start generated code]*/
2538
2539
static PyObject *
2540
_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
2541
/*[clinic end generated code: output=c66b60d41c74f9f1 input=6125d45b9a6a5abd]*/
2542
0
{
2543
0
    self->task_log_tb = 0;
2544
2545
0
    if (self->task_state != STATE_PENDING) {
2546
0
        Py_RETURN_FALSE;
2547
0
    }
2548
2549
0
    self->task_num_cancels_requested += 1;
2550
2551
    // These three lines are controversial.  See discussion starting at
2552
    // https://github.com/python/cpython/pull/31394#issuecomment-1053545331
2553
    // and corresponding code in tasks.py.
2554
    // if (self->task_num_cancels_requested > 1) {
2555
    //     Py_RETURN_FALSE;
2556
    // }
2557
2558
0
    if (self->task_fut_waiter) {
2559
0
        PyObject *res;
2560
0
        int is_true;
2561
2562
0
        res = PyObject_CallMethodOneArg(self->task_fut_waiter,
2563
0
                                           &_Py_ID(cancel), msg);
2564
0
        if (res == NULL) {
2565
0
            return NULL;
2566
0
        }
2567
2568
0
        is_true = PyObject_IsTrue(res);
2569
0
        Py_DECREF(res);
2570
0
        if (is_true < 0) {
2571
0
            return NULL;
2572
0
        }
2573
2574
0
        if (is_true) {
2575
0
            Py_RETURN_TRUE;
2576
0
        }
2577
0
    }
2578
2579
0
    self->task_must_cancel = 1;
2580
0
    Py_XINCREF(msg);
2581
0
    Py_XSETREF(self->task_cancel_msg, msg);
2582
0
    Py_RETURN_TRUE;
2583
0
}
2584
2585
/*[clinic input]
2586
@critical_section
2587
_asyncio.Task.cancelling
2588
2589
Return the count of the task's cancellation requests.
2590
2591
This count is incremented when .cancel() is called
2592
and may be decremented using .uncancel().
2593
[clinic start generated code]*/
2594
2595
static PyObject *
2596
_asyncio_Task_cancelling_impl(TaskObj *self)
2597
/*[clinic end generated code: output=803b3af96f917d7e input=5ef89b1b38f080ee]*/
2598
/*[clinic end generated code]*/
2599
0
{
2600
0
    return PyLong_FromLong(self->task_num_cancels_requested);
2601
0
}
2602
2603
/*[clinic input]
2604
@critical_section
2605
_asyncio.Task.uncancel
2606
2607
Decrement the task's count of cancellation requests.
2608
2609
This should be used by tasks that catch CancelledError
2610
and wish to continue indefinitely until they are cancelled again.
2611
2612
Returns the remaining number of cancellation requests.
2613
[clinic start generated code]*/
2614
2615
static PyObject *
2616
_asyncio_Task_uncancel_impl(TaskObj *self)
2617
/*[clinic end generated code: output=58184d236a817d3c input=cb3220b0e5afd61d]*/
2618
/*[clinic end generated code]*/
2619
0
{
2620
0
    if (self->task_num_cancels_requested > 0) {
2621
0
        self->task_num_cancels_requested -= 1;
2622
0
        if (self->task_num_cancels_requested == 0) {
2623
0
            self->task_must_cancel = 0;
2624
0
        }
2625
0
    }
2626
0
    return PyLong_FromLong(self->task_num_cancels_requested);
2627
0
}
2628
2629
/*[clinic input]
2630
_asyncio.Task.get_stack
2631
2632
    cls: defining_class
2633
    /
2634
    *
2635
    limit: object = None
2636
2637
Return the list of stack frames for this task's coroutine.
2638
2639
If the coroutine is not done, this returns the stack where it is
2640
suspended.  If the coroutine has completed successfully or was
2641
cancelled, this returns an empty list.  If the coroutine was
2642
terminated by an exception, this returns the list of traceback
2643
frames.
2644
2645
The frames are always ordered from oldest to newest.
2646
2647
The optional limit gives the maximum number of frames to
2648
return; by default all available frames are returned.  Its
2649
meaning differs depending on whether a stack or a traceback is
2650
returned: the newest frames of a stack are returned, but the
2651
oldest frames of a traceback are returned.  (This matches the
2652
behavior of the traceback module.)
2653
2654
For reasons beyond our control, only one stack frame is
2655
returned for a suspended coroutine.
2656
[clinic start generated code]*/
2657
2658
static PyObject *
2659
_asyncio_Task_get_stack_impl(TaskObj *self, PyTypeObject *cls,
2660
                             PyObject *limit)
2661
/*[clinic end generated code: output=6774dfc10d3857fa input=8e01c9b2618ae953]*/
2662
0
{
2663
0
    asyncio_state *state = get_asyncio_state_by_cls(cls);
2664
0
    PyObject *stack[] = {(PyObject *)self, limit};
2665
0
    return PyObject_Vectorcall(state->asyncio_task_get_stack_func,
2666
0
                               stack, 2, NULL);
2667
0
}
2668
2669
/*[clinic input]
2670
_asyncio.Task.print_stack
2671
2672
    cls: defining_class
2673
    /
2674
    *
2675
    limit: object = None
2676
    file: object = None
2677
2678
Print the stack or traceback for this task's coroutine.
2679
2680
This produces output similar to that of the traceback module,
2681
for the frames retrieved by get_stack().  The limit argument
2682
is passed to get_stack().  The file argument is an I/O stream
2683
to which the output is written; by default output is written
2684
to sys.stderr.
2685
[clinic start generated code]*/
2686
2687
static PyObject *
2688
_asyncio_Task_print_stack_impl(TaskObj *self, PyTypeObject *cls,
2689
                               PyObject *limit, PyObject *file)
2690
/*[clinic end generated code: output=b38affe9289ec826 input=150b35ba2d3a7dee]*/
2691
0
{
2692
0
    asyncio_state *state = get_asyncio_state_by_cls(cls);
2693
0
    PyObject *stack[] = {(PyObject *)self, limit, file};
2694
0
    return PyObject_Vectorcall(state->asyncio_task_print_stack_func,
2695
0
                               stack, 3, NULL);
2696
0
}
2697
2698
/*[clinic input]
2699
_asyncio.Task.set_result
2700
2701
    result: object
2702
    /
2703
[clinic start generated code]*/
2704
2705
static PyObject *
2706
_asyncio_Task_set_result_impl(TaskObj *self, PyObject *result)
2707
/*[clinic end generated code: output=e9d8e3cdaf18e258 input=9d1a00c07be41bab]*/
2708
0
{
2709
0
    PyErr_SetString(PyExc_RuntimeError,
2710
0
                    "Task does not support set_result operation");
2711
0
    return NULL;
2712
0
}
2713
2714
/*[clinic input]
2715
_asyncio.Task.set_exception
2716
2717
    exception: object
2718
    /
2719
[clinic start generated code]*/
2720
2721
static PyObject *
2722
_asyncio_Task_set_exception_impl(TaskObj *self, PyObject *exception)
2723
/*[clinic end generated code: output=96a91790c192cc7d input=9a8f65c83dcf893a]*/
2724
0
{
2725
0
    PyErr_SetString(PyExc_RuntimeError,
2726
0
                    "Task does not support set_exception operation");
2727
0
    return NULL;
2728
0
}
2729
2730
/*[clinic input]
2731
@critical_section
2732
_asyncio.Task.get_coro
2733
[clinic start generated code]*/
2734
2735
static PyObject *
2736
_asyncio_Task_get_coro_impl(TaskObj *self)
2737
/*[clinic end generated code: output=bcac27c8cc6c8073 input=a47f81427e39fe0c]*/
2738
0
{
2739
0
    if (self->task_coro) {
2740
0
        return Py_NewRef(self->task_coro);
2741
0
    }
2742
2743
0
    Py_RETURN_NONE;
2744
0
}
2745
2746
/*[clinic input]
2747
_asyncio.Task.get_context
2748
[clinic start generated code]*/
2749
2750
static PyObject *
2751
_asyncio_Task_get_context_impl(TaskObj *self)
2752
/*[clinic end generated code: output=6996f53d3dc01aef input=87c0b209b8fceeeb]*/
2753
0
{
2754
0
    if (self->task_context) {
2755
0
        return Py_NewRef(self->task_context);
2756
0
    }
2757
2758
0
    Py_RETURN_NONE;
2759
0
}
2760
2761
/*[clinic input]
2762
@critical_section
2763
_asyncio.Task.get_name
2764
[clinic start generated code]*/
2765
2766
static PyObject *
2767
_asyncio_Task_get_name_impl(TaskObj *self)
2768
/*[clinic end generated code: output=0ecf1570c3b37a8f input=92a8f30c85034249]*/
2769
0
{
2770
0
    if (self->task_name) {
2771
0
        if (PyLong_CheckExact(self->task_name)) {
2772
0
            PyObject *name = PyUnicode_FromFormat("Task-%S", self->task_name);
2773
0
            if (name == NULL) {
2774
0
                return NULL;
2775
0
            }
2776
0
            Py_SETREF(self->task_name, name);
2777
0
        }
2778
0
        return Py_NewRef(self->task_name);
2779
0
    }
2780
2781
0
    Py_RETURN_NONE;
2782
0
}
2783
2784
/*[clinic input]
2785
@critical_section
2786
_asyncio.Task.set_name
2787
2788
    value: object
2789
    /
2790
[clinic start generated code]*/
2791
2792
static PyObject *
2793
_asyncio_Task_set_name_impl(TaskObj *self, PyObject *value)
2794
/*[clinic end generated code: output=f88ff4c0d64a9a6f input=e8d400ad64bad799]*/
2795
0
{
2796
0
    if (!PyUnicode_CheckExact(value)) {
2797
0
        value = PyObject_Str(value);
2798
0
        if (value == NULL) {
2799
0
            return NULL;
2800
0
        }
2801
0
    } else {
2802
0
        Py_INCREF(value);
2803
0
    }
2804
2805
0
    Py_XSETREF(self->task_name, value);
2806
0
    Py_RETURN_NONE;
2807
0
}
2808
2809
static void
2810
TaskObj_finalize(PyObject *op)
2811
0
{
2812
0
    TaskObj *task = (TaskObj*)op;
2813
0
    PyObject *context;
2814
0
    PyObject *message = NULL;
2815
0
    PyObject *func;
2816
2817
0
    if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2818
0
        goto done;
2819
0
    }
2820
2821
    /* Save the current exception, if any. */
2822
0
    PyObject *exc = PyErr_GetRaisedException();
2823
2824
0
    context = PyDict_New();
2825
0
    if (context == NULL) {
2826
0
        goto finally;
2827
0
    }
2828
2829
0
    message = PyUnicode_FromString("Task was destroyed but it is pending!");
2830
0
    if (message == NULL) {
2831
0
        goto finally;
2832
0
    }
2833
2834
0
    if (PyDict_SetItem(context, &_Py_ID(message), message) < 0 ||
2835
0
        PyDict_SetItem(context, &_Py_ID(task), (PyObject*)task) < 0)
2836
0
    {
2837
0
        goto finally;
2838
0
    }
2839
2840
0
    if (task->task_source_tb != NULL) {
2841
0
        if (PyDict_SetItem(context, &_Py_ID(source_traceback),
2842
0
                              task->task_source_tb) < 0)
2843
0
        {
2844
0
            goto finally;
2845
0
        }
2846
0
    }
2847
2848
0
    func = PyObject_GetAttr(task->task_loop, &_Py_ID(call_exception_handler));
2849
0
    if (func != NULL) {
2850
0
        PyObject *res = PyObject_CallOneArg(func, context);
2851
0
        if (res == NULL) {
2852
0
            PyErr_FormatUnraisable("Exception ignored while calling asyncio "
2853
0
                                   "function %R", func);
2854
0
        }
2855
0
        else {
2856
0
            Py_DECREF(res);
2857
0
        }
2858
0
        Py_DECREF(func);
2859
0
    }
2860
2861
0
finally:
2862
0
    Py_XDECREF(context);
2863
0
    Py_XDECREF(message);
2864
2865
    /* Restore the saved exception. */
2866
0
    PyErr_SetRaisedException(exc);
2867
2868
0
done:
2869
0
    FutureObj_finalize((PyObject*)task);
2870
0
}
2871
2872
static void TaskObj_dealloc(PyObject *);  /* Needs Task_CheckExact */
2873
2874
static PyMethodDef TaskType_methods[] = {
2875
    _ASYNCIO_FUTURE_RESULT_METHODDEF
2876
    _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
2877
    _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2878
    _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2879
    _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2880
    _ASYNCIO_FUTURE_DONE_METHODDEF
2881
    _ASYNCIO_TASK_SET_RESULT_METHODDEF
2882
    _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
2883
    _ASYNCIO_TASK_CANCEL_METHODDEF
2884
    _ASYNCIO_TASK_CANCELLING_METHODDEF
2885
    _ASYNCIO_TASK_UNCANCEL_METHODDEF
2886
    _ASYNCIO_TASK_GET_STACK_METHODDEF
2887
    _ASYNCIO_TASK_PRINT_STACK_METHODDEF
2888
    _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
2889
    _ASYNCIO_TASK_GET_NAME_METHODDEF
2890
    _ASYNCIO_TASK_SET_NAME_METHODDEF
2891
    _ASYNCIO_TASK_GET_CORO_METHODDEF
2892
    _ASYNCIO_TASK_GET_CONTEXT_METHODDEF
2893
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS,
2894
    PyDoc_STR("Tasks are generic over the return type of their wrapped coroutines")},
2895
    {NULL, NULL}        /* Sentinel */
2896
};
2897
2898
static PyGetSetDef TaskType_getsetlist[] = {
2899
    _ASYNCIO_TASK__LOG_DESTROY_PENDING_GETSETDEF
2900
    _ASYNCIO_TASK__MUST_CANCEL_GETSETDEF
2901
    _ASYNCIO_TASK__CORO_GETSETDEF
2902
    _ASYNCIO_TASK__FUT_WAITER_GETSETDEF
2903
    {NULL} /* Sentinel */
2904
};
2905
2906
static PyType_Slot Task_slots[] = {
2907
    {Py_tp_dealloc, TaskObj_dealloc},
2908
    {Py_tp_repr, TaskObj_repr},
2909
    {Py_tp_doc, (void *)_asyncio_Task___init____doc__},
2910
    {Py_tp_traverse, TaskObj_traverse},
2911
    {Py_tp_clear, TaskObj_clear},
2912
    {Py_tp_iter, future_new_iter},
2913
    {Py_tp_methods, TaskType_methods},
2914
    {Py_tp_getset, TaskType_getsetlist},
2915
    {Py_tp_init, _asyncio_Task___init__},
2916
    {Py_tp_new, PyType_GenericNew},
2917
    {Py_tp_finalize, TaskObj_finalize},
2918
2919
    // async slots
2920
    {Py_am_await, future_new_iter},
2921
    {0, NULL},
2922
};
2923
2924
static PyType_Spec Task_spec = {
2925
    .name = "_asyncio.Task",
2926
    .basicsize = sizeof(TaskObj),
2927
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
2928
              Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT |
2929
              Py_TPFLAGS_MANAGED_WEAKREF),
2930
    .slots = Task_slots,
2931
};
2932
2933
static void
2934
TaskObj_dealloc(PyObject *self)
2935
0
{
2936
0
    if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2937
0
        return; // resurrected
2938
0
    }
2939
    // Untrack the object before unregistering the task, since the
2940
    // latter can cause a stop-the-world pause, after which another
2941
    // thread might call the GC and reach the object while it is
2942
    // semi-deallocated but still tracked
2943
0
    PyObject_GC_UnTrack(self);
2944
2945
    // unregister the task after finalization so that
2946
    // if the task gets resurrected, it remains registered
2947
0
    unregister_task((TaskObj *)self);
2948
2949
0
    PyTypeObject *tp = Py_TYPE(self);
2950
0
    PyObject_ClearWeakRefs(self);
2951
2952
0
    (void)TaskObj_clear(self);
2953
0
    tp->tp_free(self);
2954
0
    Py_DECREF(tp);
2955
0
}
2956
2957
static int
2958
task_call_step_soon(asyncio_state *state, TaskObj *task, PyObject *arg)
2959
0
{
2960
0
    PyObject *cb = TaskStepMethWrapper_new(task, arg);
2961
0
    if (cb == NULL) {
2962
0
        return -1;
2963
0
    }
2964
2965
0
    int ret = call_soon(state, task->task_loop, cb, NULL, task->task_context);
2966
0
    Py_DECREF(cb);
2967
0
    return ret;
2968
0
}
2969
2970
static PyObject *
2971
task_set_error_soon(asyncio_state *state, TaskObj *task, PyObject *et,
2972
                    const char *format, ...)
2973
0
{
2974
0
    PyObject* msg;
2975
2976
0
    va_list vargs;
2977
0
    va_start(vargs, format);
2978
0
    msg = PyUnicode_FromFormatV(format, vargs);
2979
0
    va_end(vargs);
2980
2981
0
    if (msg == NULL) {
2982
0
        return NULL;
2983
0
    }
2984
2985
0
    PyObject *e = PyObject_CallOneArg(et, msg);
2986
0
    Py_DECREF(msg);
2987
0
    if (e == NULL) {
2988
0
        return NULL;
2989
0
    }
2990
2991
0
    if (task_call_step_soon(state, task, e) == -1) {
2992
0
        Py_DECREF(e);
2993
0
        return NULL;
2994
0
    }
2995
2996
0
    Py_DECREF(e);
2997
0
    Py_RETURN_NONE;
2998
0
}
2999
3000
static inline int
3001
gen_status_from_result(PyObject **result)
3002
0
{
3003
0
    if (*result != NULL) {
3004
0
        return PYGEN_NEXT;
3005
0
    }
3006
0
    if (_PyGen_FetchStopIterationValue(result) == 0) {
3007
0
        return PYGEN_RETURN;
3008
0
    }
3009
3010
0
    assert(PyErr_Occurred());
3011
0
    return PYGEN_ERROR;
3012
0
}
3013
3014
static PyObject *
3015
task_step_impl(asyncio_state *state, TaskObj *task, PyObject *exc)
3016
0
{
3017
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(task);
3018
3019
0
    int clear_exc = 0;
3020
0
    PyObject *result = NULL;
3021
0
    PyObject *coro;
3022
0
    PyObject *o;
3023
3024
0
    if (task->task_state != STATE_PENDING) {
3025
0
        PyErr_Format(state->asyncio_InvalidStateError,
3026
0
                     "__step(): already done: %R %R",
3027
0
                     task,
3028
0
                     exc ? exc : Py_None);
3029
0
        goto fail;
3030
0
    }
3031
3032
0
    if (task->task_must_cancel) {
3033
0
        assert(exc != Py_None);
3034
3035
        /* Replace exc with a CancelledError unless it already is one, or
3036
        it is SystemExit/KeyboardInterrupt, which must propagate
3037
        unchanged (gh-108549). */
3038
0
        if (!exc ||
3039
0
            (!PyErr_GivenExceptionMatches(exc, state->asyncio_CancelledError) &&
3040
0
            !PyErr_GivenExceptionMatches(exc, PyExc_KeyboardInterrupt) &&
3041
0
            !PyErr_GivenExceptionMatches(exc, PyExc_SystemExit))) {
3042
0
            exc = create_cancelled_error(state, (FutureObj*)task);
3043
3044
0
            if (!exc) {
3045
0
                goto fail;
3046
0
            }
3047
0
            clear_exc = 1;
3048
0
        }
3049
3050
0
        task->task_must_cancel = 0;
3051
0
    }
3052
3053
0
    Py_CLEAR(task->task_fut_waiter);
3054
3055
0
    coro = task->task_coro;
3056
0
    if (coro == NULL) {
3057
0
        PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
3058
0
        if (clear_exc) {
3059
            /* We created 'exc' during this call */
3060
0
            Py_DECREF(exc);
3061
0
        }
3062
0
        return NULL;
3063
0
    }
3064
3065
0
    int gen_status = PYGEN_ERROR;
3066
0
    if (exc == NULL) {
3067
0
        gen_status = PyIter_Send(coro, Py_None, &result);
3068
0
    }
3069
0
    else {
3070
0
        result = PyObject_CallMethodOneArg(coro, &_Py_ID(throw), exc);
3071
0
        gen_status = gen_status_from_result(&result);
3072
0
        if (clear_exc) {
3073
            /* We created 'exc' during this call */
3074
0
            Py_DECREF(exc);
3075
0
        }
3076
0
    }
3077
3078
0
    if (gen_status == PYGEN_RETURN || gen_status == PYGEN_ERROR) {
3079
0
        if (result != NULL) {
3080
            /* The error is StopIteration and that means that
3081
               the underlying coroutine has resolved */
3082
3083
0
            PyObject *tmp;
3084
0
            if (task->task_must_cancel) {
3085
                // Task is cancelled right before coro stops.
3086
0
                task->task_must_cancel = 0;
3087
0
                tmp = future_cancel(state, (FutureObj*)task,
3088
0
                                    task->task_cancel_msg);
3089
0
            }
3090
0
            else {
3091
0
                tmp = future_set_result(state, (FutureObj*)task, result);
3092
0
            }
3093
3094
0
            Py_DECREF(result);
3095
3096
0
            if (tmp == NULL) {
3097
0
                return NULL;
3098
0
            }
3099
0
            Py_DECREF(tmp);
3100
0
            Py_RETURN_NONE;
3101
0
        }
3102
3103
0
        if (PyErr_ExceptionMatches(state->asyncio_CancelledError)) {
3104
            /* CancelledError */
3105
3106
0
            PyObject *exc = PyErr_GetRaisedException();
3107
0
            assert(exc);
3108
3109
0
            FutureObj *fut = (FutureObj*)task;
3110
            /* transfer ownership */
3111
0
            fut->fut_cancelled_exc = exc;
3112
3113
0
            return future_cancel(state, fut, NULL);
3114
0
        }
3115
3116
        /* Some other exception; pop it and call Task.set_exception() */
3117
0
        PyObject *exc = PyErr_GetRaisedException();
3118
0
        assert(exc);
3119
3120
0
        o = future_set_exception(state, (FutureObj*)task, exc);
3121
0
        if (!o) {
3122
            /* An exception in Task.set_exception() */
3123
0
            Py_DECREF(exc);
3124
0
            goto fail;
3125
0
        }
3126
0
        assert(o == Py_None);
3127
0
        Py_DECREF(o);
3128
3129
0
        if (PyErr_GivenExceptionMatches(exc, PyExc_KeyboardInterrupt) ||
3130
0
            PyErr_GivenExceptionMatches(exc, PyExc_SystemExit))
3131
0
        {
3132
            /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
3133
0
            PyErr_SetRaisedException(exc);
3134
0
            goto fail;
3135
0
        }
3136
3137
0
        Py_DECREF(exc);
3138
3139
0
        Py_RETURN_NONE;
3140
0
    }
3141
3142
0
    PyObject *ret = task_step_handle_result_impl(state, task, result);
3143
0
    return ret;
3144
3145
0
fail:
3146
0
    return NULL;
3147
0
}
3148
3149
3150
static PyObject *
3151
task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *result)
3152
0
{
3153
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(task);
3154
3155
0
    int res;
3156
0
    PyObject *o;
3157
3158
0
    if (result == (PyObject*)task) {
3159
        /* We have a task that wants to await on itself */
3160
0
        goto self_await;
3161
0
    }
3162
3163
    /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
3164
0
    if (Future_CheckExact(state, result) || Task_CheckExact(state, result)) {
3165
0
        PyObject *wrapper;
3166
0
        PyObject *tmp;
3167
0
        FutureObj *fut = (FutureObj*)result;
3168
3169
        /* Check if `result` future is attached to a different loop */
3170
0
        if (fut->fut_loop != task->task_loop) {
3171
0
            goto different_loop;
3172
0
        }
3173
3174
0
        if (!fut->fut_blocking) {
3175
0
            goto yield_insteadof_yf;
3176
0
        }
3177
0
        int res;
3178
0
        Py_BEGIN_CRITICAL_SECTION(result);
3179
0
        res = future_awaited_by_add(state, (FutureObj *)result, (PyObject *)task);
3180
0
        Py_END_CRITICAL_SECTION();
3181
0
        if (res) {
3182
0
            goto fail;
3183
0
        }
3184
3185
0
        fut->fut_blocking = 0;
3186
3187
        /* result.add_done_callback(task._wakeup) */
3188
0
        wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
3189
0
        if (wrapper == NULL) {
3190
0
            goto fail;
3191
0
        }
3192
0
        Py_BEGIN_CRITICAL_SECTION(result);
3193
0
        tmp = future_add_done_callback(state,
3194
0
            (FutureObj*)result, wrapper, task->task_context);
3195
0
        Py_END_CRITICAL_SECTION();
3196
0
        Py_DECREF(wrapper);
3197
0
        if (tmp == NULL) {
3198
0
            goto fail;
3199
0
        }
3200
0
        Py_DECREF(tmp);
3201
3202
        /* task._fut_waiter = result */
3203
0
        task->task_fut_waiter = result;  /* no incref is necessary */
3204
3205
0
        if (task->task_must_cancel) {
3206
0
            PyObject *r;
3207
0
            int is_true;
3208
3209
            // Beware: An evil `__getattribute__` could
3210
            // prematurely delete task->task_cancel_msg before the
3211
            // task is cancelled, thereby causing a UAF crash.
3212
            //
3213
            // See https://github.com/python/cpython/issues/126138
3214
0
            PyObject *task_cancel_msg = Py_NewRef(task->task_cancel_msg);
3215
0
            r = PyObject_CallMethodOneArg(result, &_Py_ID(cancel),
3216
0
                                          task_cancel_msg);
3217
0
            Py_DECREF(task_cancel_msg);
3218
3219
0
            if (r == NULL) {
3220
0
                return NULL;
3221
0
            }
3222
0
            is_true = PyObject_IsTrue(r);
3223
0
            Py_DECREF(r);
3224
0
            if (is_true < 0) {
3225
0
                return NULL;
3226
0
            }
3227
0
            else if (is_true) {
3228
0
                task->task_must_cancel = 0;
3229
0
            }
3230
0
        }
3231
3232
0
        Py_RETURN_NONE;
3233
0
    }
3234
3235
    /* Check if `result` is None */
3236
0
    if (result == Py_None) {
3237
        /* Bare yield relinquishes control for one event loop iteration. */
3238
0
        if (task_call_step_soon(state, task, NULL)) {
3239
0
            goto fail;
3240
0
        }
3241
0
        return result;
3242
0
    }
3243
3244
    /* Check if `result` is a Future-compatible object */
3245
0
    if (PyObject_GetOptionalAttr(result, &_Py_ID(_asyncio_future_blocking), &o) < 0) {
3246
0
        goto fail;
3247
0
    }
3248
0
    if (o != NULL && o != Py_None) {
3249
        /* `result` is a Future-compatible object */
3250
0
        PyObject *wrapper;
3251
0
        PyObject *tmp;
3252
3253
0
        int blocking = PyObject_IsTrue(o);
3254
0
        Py_DECREF(o);
3255
0
        if (blocking < 0) {
3256
0
            goto fail;
3257
0
        }
3258
3259
        /* Check if `result` future is attached to a different loop */
3260
0
        PyObject *oloop = get_future_loop(state, result);
3261
0
        if (oloop == NULL) {
3262
0
            goto fail;
3263
0
        }
3264
0
        if (oloop != task->task_loop) {
3265
0
            Py_DECREF(oloop);
3266
0
            goto different_loop;
3267
0
        }
3268
0
        Py_DECREF(oloop);
3269
3270
0
        if (!blocking) {
3271
0
            goto yield_insteadof_yf;
3272
0
        }
3273
3274
0
        if (TaskOrFuture_Check(state, result)) {
3275
0
            int res;
3276
0
            Py_BEGIN_CRITICAL_SECTION(result);
3277
0
            res = future_awaited_by_add(state, (FutureObj *)result, (PyObject *)task);
3278
0
            Py_END_CRITICAL_SECTION();
3279
0
            if (res) {
3280
0
                goto fail;
3281
0
            }
3282
0
        }
3283
3284
        /* result._asyncio_future_blocking = False */
3285
0
        if (PyObject_SetAttr(
3286
0
                result, &_Py_ID(_asyncio_future_blocking), Py_False) == -1) {
3287
0
            goto fail;
3288
0
        }
3289
3290
0
        wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
3291
0
        if (wrapper == NULL) {
3292
0
            goto fail;
3293
0
        }
3294
3295
        /* result.add_done_callback(task._wakeup) */
3296
0
        PyObject *add_cb = PyObject_GetAttr(
3297
0
            result, &_Py_ID(add_done_callback));
3298
0
        if (add_cb == NULL) {
3299
0
            Py_DECREF(wrapper);
3300
0
            goto fail;
3301
0
        }
3302
0
        PyObject *stack[2];
3303
0
        stack[0] = wrapper;
3304
0
        stack[1] = (PyObject *)task->task_context;
3305
0
        EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, add_cb);
3306
0
        tmp = PyObject_Vectorcall(add_cb, stack, 1, state->context_kwname);
3307
0
        Py_DECREF(add_cb);
3308
0
        Py_DECREF(wrapper);
3309
0
        if (tmp == NULL) {
3310
0
            goto fail;
3311
0
        }
3312
0
        Py_DECREF(tmp);
3313
3314
        /* task._fut_waiter = result */
3315
0
        task->task_fut_waiter = result;  /* no incref is necessary */
3316
3317
0
        if (task->task_must_cancel) {
3318
0
            PyObject *r;
3319
0
            int is_true;
3320
3321
            // Beware: An evil `__getattribute__` could
3322
            // prematurely delete task->task_cancel_msg before the
3323
            // task is cancelled, thereby causing a UAF crash.
3324
            //
3325
            // See https://github.com/python/cpython/issues/126138
3326
0
            PyObject *task_cancel_msg = Py_NewRef(task->task_cancel_msg);
3327
0
            r = PyObject_CallMethodOneArg(result, &_Py_ID(cancel),
3328
0
                                          task_cancel_msg);
3329
0
            Py_DECREF(task_cancel_msg);
3330
3331
0
            if (r == NULL) {
3332
0
                return NULL;
3333
0
            }
3334
0
            is_true = PyObject_IsTrue(r);
3335
0
            Py_DECREF(r);
3336
0
            if (is_true < 0) {
3337
0
                return NULL;
3338
0
            }
3339
0
            else if (is_true) {
3340
0
                task->task_must_cancel = 0;
3341
0
            }
3342
0
        }
3343
3344
0
        Py_RETURN_NONE;
3345
0
    }
3346
3347
0
    Py_XDECREF(o);
3348
    /* Check if `result` is a generator */
3349
0
    res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
3350
0
    if (res < 0) {
3351
0
        goto fail;
3352
0
    }
3353
0
    if (res) {
3354
        /* `result` is a generator */
3355
0
        o = task_set_error_soon(
3356
0
            state, task, PyExc_RuntimeError,
3357
0
            "yield was used instead of yield from for "
3358
0
            "generator in task %R with %R", task, result);
3359
0
        Py_DECREF(result);
3360
0
        return o;
3361
0
    }
3362
3363
    /* The `result` is none of the above */
3364
0
    o = task_set_error_soon(
3365
0
        state, task, PyExc_RuntimeError, "Task got bad yield: %R", result);
3366
0
    Py_DECREF(result);
3367
0
    return o;
3368
3369
0
self_await:
3370
0
    o = task_set_error_soon(
3371
0
        state, task, PyExc_RuntimeError,
3372
0
        "Task cannot await on itself: %R", task);
3373
0
    Py_DECREF(result);
3374
0
    return o;
3375
3376
0
yield_insteadof_yf:
3377
0
    o = task_set_error_soon(
3378
0
        state, task, PyExc_RuntimeError,
3379
0
        "yield was used instead of yield from "
3380
0
        "in task %R with %R",
3381
0
        task, result);
3382
0
    Py_DECREF(result);
3383
0
    return o;
3384
3385
0
different_loop:
3386
0
    o = task_set_error_soon(
3387
0
        state, task, PyExc_RuntimeError,
3388
0
        "Task %R got Future %R attached to a different loop",
3389
0
        task, result);
3390
0
    Py_DECREF(result);
3391
0
    return o;
3392
3393
0
fail:
3394
0
    Py_XDECREF(result);
3395
0
    return NULL;
3396
0
}
3397
3398
static PyObject *
3399
task_step(asyncio_state *state, TaskObj *task, PyObject *exc)
3400
0
{
3401
0
    PyObject *res;
3402
3403
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3404
3405
0
    if (enter_task(ts, task->task_loop, (PyObject*)task) < 0) {
3406
0
        return NULL;
3407
0
    }
3408
3409
0
    res = task_step_impl(state, task, exc);
3410
3411
0
    if (res == NULL) {
3412
0
        PyObject *exc = PyErr_GetRaisedException();
3413
0
        leave_task(ts, task->task_loop, (PyObject*)task);
3414
0
        _PyErr_ChainExceptions1(exc);
3415
0
        return NULL;
3416
0
    }
3417
0
    else {
3418
0
        if (leave_task(ts, task->task_loop, (PyObject*)task) < 0) {
3419
0
            Py_DECREF(res);
3420
0
            return NULL;
3421
0
        }
3422
0
        else {
3423
0
            return res;
3424
0
        }
3425
0
    }
3426
0
}
3427
3428
static int
3429
task_eager_start(_PyThreadStateImpl *ts, asyncio_state *state, TaskObj *task)
3430
0
{
3431
0
    assert(task != NULL);
3432
0
    PyObject *prevtask = swap_current_task(ts, task->task_loop, (PyObject *)task);
3433
0
    if (prevtask == NULL) {
3434
0
        return -1;
3435
0
    }
3436
    // register the task into the linked list of tasks
3437
    // if the task completes eagerly (without suspending) then it will unregister itself
3438
    // in future_schedule_callbacks when done, otherwise
3439
    // it will continue as a regular (non-eager) asyncio task
3440
0
    register_task(ts, task);
3441
3442
0
    assert(PyContext_CheckExact(task->task_context));
3443
0
    if (_PyContext_Enter(&ts->base, task->task_context) == -1) {
3444
        // gh-157301: a failed enter must not leave the task current and registered
3445
0
        task->task_log_destroy_pending = 0;
3446
0
        PyObject *curtask = swap_current_task(ts, task->task_loop, prevtask);
3447
0
        Py_XDECREF(curtask);
3448
0
        unregister_task(task);
3449
0
        Py_DECREF(prevtask);
3450
0
        return -1;
3451
0
    }
3452
3453
0
    int retval = 0;
3454
3455
0
    PyObject *stepres;
3456
0
    Py_BEGIN_CRITICAL_SECTION(task);
3457
0
    stepres = task_step_impl(state, task, NULL);
3458
0
    Py_END_CRITICAL_SECTION();
3459
0
    if (stepres == NULL) {
3460
0
        PyObject *exc = PyErr_GetRaisedException();
3461
0
        _PyErr_ChainExceptions1(exc);
3462
0
        retval = -1;
3463
0
    } else {
3464
0
        Py_DECREF(stepres);
3465
0
    }
3466
3467
0
    PyObject *curtask = swap_current_task(ts, task->task_loop, prevtask);
3468
0
    Py_DECREF(prevtask);
3469
0
    if (curtask == NULL) {
3470
0
        retval = -1;
3471
0
    } else {
3472
0
        assert(curtask == (PyObject *)task);
3473
0
        Py_DECREF(curtask);
3474
0
    }
3475
3476
0
    if (_PyContext_Exit(&ts->base, task->task_context) == -1) {
3477
0
        retval = -1;
3478
0
    }
3479
3480
0
    if (task->task_state != STATE_PENDING) {
3481
        // This seems to really help performance on pyperformance benchmarks
3482
0
        clear_task_coro(task);
3483
0
    }
3484
3485
0
    return retval;
3486
0
}
3487
3488
static PyObject *
3489
task_wakeup_lock_held(TaskObj *task, PyObject *o)
3490
0
{
3491
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(task);
3492
3493
0
    PyObject *result;
3494
0
    assert(o);
3495
3496
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)task);
3497
3498
0
    if (TaskOrFuture_Check(state, o)) {
3499
0
        int res;
3500
0
        Py_BEGIN_CRITICAL_SECTION(o);
3501
0
        res = future_awaited_by_discard(state, (FutureObj *)o, (PyObject *)task);
3502
0
        Py_END_CRITICAL_SECTION();
3503
0
        if (res) {
3504
0
            return NULL;
3505
0
        }
3506
0
    }
3507
3508
0
    if (Future_CheckExact(state, o) || Task_CheckExact(state, o)) {
3509
0
        PyObject *fut_result = NULL;
3510
0
        int res;
3511
0
        Py_BEGIN_CRITICAL_SECTION(o);
3512
0
        res = future_get_result(state, (FutureObj*)o, &fut_result);
3513
0
        Py_END_CRITICAL_SECTION();
3514
0
        switch(res) {
3515
0
        case -1:
3516
0
            assert(fut_result == NULL);
3517
0
            break; /* exception raised */
3518
0
        case 0:
3519
0
            Py_DECREF(fut_result);
3520
0
            return task_step(state, task, NULL);
3521
0
        default:
3522
0
            assert(res == 1);
3523
0
            result = task_step(state, task, fut_result);
3524
0
            Py_DECREF(fut_result);
3525
0
            return result;
3526
0
        }
3527
0
    }
3528
0
    else {
3529
0
        PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
3530
0
        if (fut_result != NULL) {
3531
0
            Py_DECREF(fut_result);
3532
0
            return task_step(state, task, NULL);
3533
0
        }
3534
        /* exception raised */
3535
0
    }
3536
3537
0
    PyObject *exc = PyErr_GetRaisedException();
3538
0
    assert(exc);
3539
3540
0
    result = task_step(state, task, exc);
3541
3542
0
    Py_DECREF(exc);
3543
3544
0
    return result;
3545
0
}
3546
3547
static PyObject *
3548
task_wakeup(PyObject *op, PyObject *arg)
3549
0
{
3550
0
    TaskObj *task = (TaskObj*)op;
3551
0
    PyObject *res;
3552
0
    Py_BEGIN_CRITICAL_SECTION(task);
3553
0
    res = task_wakeup_lock_held(task, arg);
3554
0
    Py_END_CRITICAL_SECTION();
3555
0
    return res;
3556
0
}
3557
3558
3559
/*********************** Functions **************************/
3560
3561
3562
/*[clinic input]
3563
_asyncio._get_running_loop
3564
3565
Return the running event loop or None.
3566
3567
This is a low-level function intended to be used by event loops.
3568
This function is thread-specific.
3569
3570
[clinic start generated code]*/
3571
3572
static PyObject *
3573
_asyncio__get_running_loop_impl(PyObject *module)
3574
/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3575
0
{
3576
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3577
0
    PyObject *loop = Py_XNewRef(ts->asyncio_running_loop);
3578
0
    if (loop == NULL) {
3579
        /* There's no currently running event loop */
3580
0
        Py_RETURN_NONE;
3581
0
    }
3582
0
    return loop;
3583
0
}
3584
3585
/*[clinic input]
3586
_asyncio._set_running_loop
3587
    loop: 'O'
3588
    /
3589
3590
Set the running event loop.
3591
3592
This is a low-level function intended to be used by event loops.
3593
This function is thread-specific.
3594
[clinic start generated code]*/
3595
3596
static PyObject *
3597
_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3598
/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3599
0
{
3600
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3601
0
    if (loop == Py_None) {
3602
0
        loop = NULL;
3603
0
    }
3604
0
    Py_XSETREF(ts->asyncio_running_loop, Py_XNewRef(loop));
3605
0
    Py_RETURN_NONE;
3606
0
}
3607
3608
/*[clinic input]
3609
_asyncio.get_event_loop
3610
3611
Return an asyncio event loop.
3612
3613
When called from a coroutine or a callback (e.g. scheduled with
3614
call_soon or similar API), this function will always return the
3615
running event loop.
3616
3617
If there is no running event loop set, the function will return
3618
the loop set by `set_event_loop()`, or raise a RuntimeError if
3619
no loop has been set.
3620
[clinic start generated code]*/
3621
3622
static PyObject *
3623
_asyncio_get_event_loop_impl(PyObject *module)
3624
/*[clinic end generated code: output=2a2d8b2f824c648b input=fa104f00dc7995dc]*/
3625
0
{
3626
0
    asyncio_state *state = get_asyncio_state(module);
3627
0
    return get_event_loop(state);
3628
0
}
3629
3630
/*[clinic input]
3631
_asyncio.get_running_loop
3632
3633
Return the running event loop.  Raise a RuntimeError if there is none.
3634
3635
This function is thread-specific.
3636
[clinic start generated code]*/
3637
3638
static PyObject *
3639
_asyncio_get_running_loop_impl(PyObject *module)
3640
/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3641
0
{
3642
0
    PyObject *loop;
3643
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3644
0
    loop = Py_XNewRef(ts->asyncio_running_loop);
3645
0
    if (loop == NULL) {
3646
        /* There's no currently running event loop */
3647
0
        PyErr_SetString(
3648
0
            PyExc_RuntimeError, "no running event loop");
3649
0
        return NULL;
3650
0
    }
3651
0
    return loop;
3652
0
}
3653
3654
/*[clinic input]
3655
_asyncio._register_task
3656
3657
    task: object
3658
3659
Register a new task in asyncio as executed by loop.
3660
3661
Returns None.
3662
[clinic start generated code]*/
3663
3664
static PyObject *
3665
_asyncio__register_task_impl(PyObject *module, PyObject *task)
3666
/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
3667
0
{
3668
0
    asyncio_state *state = get_asyncio_state(module);
3669
0
    if (Task_Check(state, task)) {
3670
        // task is an asyncio.Task instance or subclass, use efficient
3671
        // linked-list implementation.
3672
0
        _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3673
0
        register_task(ts, (TaskObj *)task);
3674
0
        Py_RETURN_NONE;
3675
0
    }
3676
    // As task does not inherit from asyncio.Task, fallback to less efficient
3677
    // weakset implementation.
3678
0
    PyObject *res = PyObject_CallMethodOneArg(state->non_asyncio_tasks,
3679
0
                                              &_Py_ID(add), task);
3680
0
    if (res == NULL) {
3681
0
        return NULL;
3682
0
    }
3683
0
    Py_DECREF(res);
3684
0
    Py_RETURN_NONE;
3685
0
}
3686
3687
/*[clinic input]
3688
_asyncio._register_eager_task
3689
3690
    task: object
3691
3692
Register a new task in asyncio as executed by loop.
3693
3694
Returns None.
3695
[clinic start generated code]*/
3696
3697
static PyObject *
3698
_asyncio__register_eager_task_impl(PyObject *module, PyObject *task)
3699
/*[clinic end generated code: output=dfe1d45367c73f1a input=237f684683398c51]*/
3700
0
{
3701
0
    asyncio_state *state = get_asyncio_state(module);
3702
3703
0
    if (Task_Check(state, task)) {
3704
        // task is an asyncio.Task instance or subclass, use efficient
3705
        // linked-list implementation.
3706
0
        _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3707
0
        register_task(ts, (TaskObj *)task);
3708
0
        Py_RETURN_NONE;
3709
0
    }
3710
3711
0
    if (PySet_Add(state->non_asyncio_eager_tasks, task) < 0) {
3712
0
        return NULL;
3713
0
    }
3714
3715
0
    Py_RETURN_NONE;
3716
0
}
3717
3718
3719
/*[clinic input]
3720
_asyncio._unregister_task
3721
3722
    task: object
3723
3724
Unregister a task.
3725
3726
Returns None.
3727
[clinic start generated code]*/
3728
3729
static PyObject *
3730
_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3731
/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
3732
0
{
3733
0
    asyncio_state *state = get_asyncio_state(module);
3734
0
    if (Task_Check(state, task)) {
3735
0
        unregister_task((TaskObj *)task);
3736
0
        Py_RETURN_NONE;
3737
0
    }
3738
0
    PyObject *res = PyObject_CallMethodOneArg(state->non_asyncio_tasks,
3739
0
                                              &_Py_ID(discard), task);
3740
0
    if (res == NULL) {
3741
0
        return NULL;
3742
0
    }
3743
0
    Py_DECREF(res);
3744
0
    Py_RETURN_NONE;
3745
0
}
3746
3747
/*[clinic input]
3748
_asyncio._unregister_eager_task
3749
3750
    task: object
3751
3752
Unregister a task.
3753
3754
Returns None.
3755
[clinic start generated code]*/
3756
3757
static PyObject *
3758
_asyncio__unregister_eager_task_impl(PyObject *module, PyObject *task)
3759
/*[clinic end generated code: output=a426922bd07f23d1 input=9d07401ef14ee048]*/
3760
0
{
3761
0
    asyncio_state *state = get_asyncio_state(module);
3762
0
    if (Task_Check(state, task)) {
3763
        // task is an asyncio.Task instance or subclass, use efficient
3764
        // linked-list implementation.
3765
0
        unregister_task((TaskObj *)task);
3766
0
        Py_RETURN_NONE;
3767
0
    }
3768
3769
0
    if (PySet_Discard(state->non_asyncio_eager_tasks, task) < 0) {
3770
0
        return NULL;
3771
0
    }
3772
3773
0
    Py_RETURN_NONE;
3774
0
}
3775
3776
3777
/*[clinic input]
3778
_asyncio._enter_task
3779
3780
    loop: object
3781
    task: object
3782
3783
Enter into task execution or resume suspended task.
3784
3785
Task belongs to loop.
3786
3787
Returns None.
3788
[clinic start generated code]*/
3789
3790
static PyObject *
3791
_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3792
/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3793
0
{
3794
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3795
0
    if (enter_task(ts, loop, task) < 0) {
3796
0
        return NULL;
3797
0
    }
3798
0
    Py_RETURN_NONE;
3799
0
}
3800
3801
3802
/*[clinic input]
3803
_asyncio._leave_task
3804
3805
    loop: object
3806
    task: object
3807
3808
Leave task execution or suspend a task.
3809
3810
Task belongs to loop.
3811
3812
Returns None.
3813
[clinic start generated code]*/
3814
3815
static PyObject *
3816
_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3817
/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3818
0
{
3819
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3820
0
    if (leave_task(ts, loop, task) < 0) {
3821
0
        return NULL;
3822
0
    }
3823
0
    Py_RETURN_NONE;
3824
0
}
3825
3826
3827
/*[clinic input]
3828
@permit_long_summary
3829
_asyncio._swap_current_task
3830
3831
    loop: object
3832
    task: object
3833
3834
Temporarily swap in the supplied task and return the original one (or None).
3835
3836
This is intended for use during eager coroutine execution.
3837
3838
[clinic start generated code]*/
3839
3840
static PyObject *
3841
_asyncio__swap_current_task_impl(PyObject *module, PyObject *loop,
3842
                                 PyObject *task)
3843
/*[clinic end generated code: output=9f88de958df74c7e input=ec14ed25855e3068]*/
3844
0
{
3845
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3846
0
    return swap_current_task(ts, loop, task);
3847
0
}
3848
3849
3850
/*[clinic input]
3851
_asyncio.current_task
3852
3853
    loop: object = None
3854
3855
Return a currently executed task.
3856
3857
[clinic start generated code]*/
3858
3859
static PyObject *
3860
_asyncio_current_task_impl(PyObject *module, PyObject *loop)
3861
/*[clinic end generated code: output=fe15ac331a7f981a input=58910f61a5627112]*/
3862
0
{
3863
0
    if (loop == Py_None) {
3864
0
        loop = _asyncio_get_running_loop_impl(module);
3865
0
        if (loop == NULL) {
3866
0
            return NULL;
3867
0
        }
3868
0
    } else {
3869
0
        Py_INCREF(loop);
3870
0
    }
3871
3872
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3873
    // Fast path for the current running loop of current thread
3874
    // no locking or stop the world pause is required
3875
0
    if (ts->asyncio_running_loop == loop) {
3876
0
        if (ts->asyncio_running_task != NULL) {
3877
0
            Py_DECREF(loop);
3878
0
            return Py_NewRef(ts->asyncio_running_task);
3879
0
        }
3880
0
        Py_DECREF(loop);
3881
0
        Py_RETURN_NONE;
3882
0
    }
3883
3884
0
    PyObject *ret = Py_None;
3885
    // Stop the world and traverse the per-thread current tasks
3886
    // and return the task if the loop matches
3887
0
    PyInterpreterState *interp = ts->base.interp;
3888
0
    _PyEval_StopTheWorld(interp);
3889
0
    _Py_FOR_EACH_TSTATE_BEGIN(interp, p) {
3890
0
        ts = (_PyThreadStateImpl *)p;
3891
0
        if (ts->asyncio_running_loop == loop) {
3892
0
            if (ts->asyncio_running_task != NULL) {
3893
0
                ret = Py_NewRef(ts->asyncio_running_task);
3894
0
            }
3895
0
            goto exit;
3896
0
        }
3897
0
    }
3898
0
exit:
3899
0
    _Py_FOR_EACH_TSTATE_END(interp);
3900
0
    _PyEval_StartTheWorld(interp);
3901
0
    Py_DECREF(loop);
3902
0
    return ret;
3903
0
}
3904
3905
3906
static inline int
3907
add_one_task(asyncio_state *state, PyObject *tasks, PyObject *task, PyObject *loop)
3908
0
{
3909
0
    assert(PySet_CheckExact(tasks));
3910
0
    if (Task_CheckExact(state, task)) {
3911
0
        int pending = 0;
3912
0
        Py_BEGIN_CRITICAL_SECTION(task);
3913
0
        pending = ((TaskObj *)task)->task_state == STATE_PENDING && ((TaskObj *)task)->task_loop == loop;
3914
0
        Py_END_CRITICAL_SECTION();
3915
0
        if (pending) {
3916
0
            if (PySet_Add(tasks, task) < 0) {
3917
0
                return -1;
3918
0
            }
3919
0
        }
3920
0
        return 0;
3921
0
    }
3922
3923
0
    PyObject *done = PyObject_CallMethodNoArgs(task, &_Py_ID(done));
3924
0
    if (done == NULL) {
3925
0
        return -1;
3926
0
    }
3927
0
    if (Py_IsTrue(done)) {
3928
0
        return 0;
3929
0
    }
3930
0
    Py_DECREF(done);
3931
0
    PyObject *task_loop = get_future_loop(state, task);
3932
0
    if (task_loop == NULL) {
3933
0
        return -1;
3934
0
    }
3935
0
    if (task_loop == loop) {
3936
0
        if (PySet_Add(tasks, task) < 0) {
3937
0
            Py_DECREF(task_loop);
3938
0
            return -1;
3939
0
        }
3940
0
    }
3941
0
    Py_DECREF(task_loop);
3942
0
    return 0;
3943
0
}
3944
3945
static inline int
3946
add_tasks_llist(struct llist_node *head, PyListObject *tasks)
3947
0
{
3948
0
    struct llist_node *node;
3949
0
    llist_for_each_safe(node, head) {
3950
0
        TaskObj *task = llist_data(node, TaskObj, task_node);
3951
0
        assert(task->task_state == STATE_PENDING);
3952
        // The linked list holds borrowed references to task
3953
        // as such it is possible that the task is concurrently
3954
        // deallocated while added to this list.
3955
        // To protect against concurrent deallocations,
3956
        // we first try to incref the task which would fail
3957
        // if it is concurrently getting deallocated in another thread,
3958
        // otherwise it gets added to the list.
3959
0
        if (_Py_TryIncref((PyObject *)task)) {
3960
0
            if (_PyList_AppendTakeRef(tasks, (PyObject *)task) < 0) {
3961
                // do not call any escaping calls here while the world is stopped.
3962
0
                return -1;
3963
0
            }
3964
0
        }
3965
0
    }
3966
0
    return 0;
3967
0
}
3968
3969
static inline int
3970
add_tasks_interp(PyInterpreterState *interp, PyListObject *tasks)
3971
0
{
3972
#ifdef Py_GIL_DISABLED
3973
    assert(interp->stoptheworld.world_stopped);
3974
#endif
3975
    // Start traversing from interpreter's linked list
3976
0
    struct llist_node *head = &interp->asyncio_tasks_head;
3977
3978
0
    if (add_tasks_llist(head, tasks) < 0) {
3979
0
        return -1;
3980
0
    }
3981
3982
0
    int ret = 0;
3983
    // traverse the task lists of thread states
3984
0
    _Py_FOR_EACH_TSTATE_BEGIN(interp, p) {
3985
0
        _PyThreadStateImpl *ts = (_PyThreadStateImpl *)p;
3986
0
        head = &ts->asyncio_tasks_head;
3987
0
        if (add_tasks_llist(head, tasks) < 0) {
3988
0
            ret = -1;
3989
0
            goto exit;
3990
0
        }
3991
0
    }
3992
0
exit:
3993
0
    _Py_FOR_EACH_TSTATE_END(interp);
3994
0
    return ret;
3995
0
}
3996
3997
/*********************** Module **************************/
3998
3999
/*[clinic input]
4000
_asyncio.all_tasks
4001
4002
    loop: object = None
4003
4004
Return a set of all tasks for the loop.
4005
4006
[clinic start generated code]*/
4007
4008
static PyObject *
4009
_asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
4010
/*[clinic end generated code: output=0e107cbb7f72aa7b input=43a1b423c2d95bfa]*/
4011
0
{
4012
0
    asyncio_state *state = get_asyncio_state(module);
4013
0
    if (loop == Py_None) {
4014
0
        loop = _asyncio_get_running_loop_impl(module);
4015
0
        if (loop == NULL) {
4016
0
            return NULL;
4017
0
        }
4018
0
    } else {
4019
0
        Py_INCREF(loop);
4020
0
    }
4021
    // First add eager tasks to the list so that we don't miss
4022
    // any tasks which graduates from eager to non-eager
4023
    // We first add all the tasks to `tasks` list and then filter
4024
    // out the tasks which are done and return it as a set.
4025
0
    PyObject *tasks = PyList_New(0);
4026
0
    if (tasks == NULL) {
4027
0
        Py_DECREF(loop);
4028
0
        return NULL;
4029
0
    }
4030
0
    if (PyList_Extend(tasks, state->non_asyncio_eager_tasks) < 0) {
4031
0
        Py_DECREF(tasks);
4032
0
        Py_DECREF(loop);
4033
0
        return NULL;
4034
0
    }
4035
0
    if (PyList_Extend(tasks, state->non_asyncio_tasks) < 0) {
4036
0
        Py_DECREF(tasks);
4037
0
        Py_DECREF(loop);
4038
0
        return NULL;
4039
0
    }
4040
4041
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
4042
0
    if (ts->asyncio_running_loop == loop) {
4043
        // Fast path for the current running loop of current thread
4044
        // no locking or stop the world pause is required
4045
0
        struct llist_node *head = &ts->asyncio_tasks_head;
4046
0
        if (add_tasks_llist(head, (PyListObject *)tasks) < 0) {
4047
0
            Py_DECREF(tasks);
4048
0
            Py_DECREF(loop);
4049
0
            return NULL;
4050
0
        }
4051
0
    }
4052
0
    else {
4053
        // Slow path for loop running in different thread
4054
0
        PyInterpreterState *interp = ts->base.interp;
4055
        // Stop the world and traverse the per-thread linked list
4056
        // of asyncio tasks for every thread, as well as the
4057
        // interpreter's linked list, and add them to `tasks`.
4058
        // The interpreter linked list is used for any lingering tasks
4059
        // whose thread state has been deallocated while the task was
4060
        // still alive. This can happen if a task is referenced by
4061
        // a different thread, in which case the task is moved to
4062
        // the interpreter's linked list from the thread's linked
4063
        // list before deallocation. See PyThreadState_Clear.
4064
        //
4065
        // The stop-the-world pause is required so that no thread
4066
        // modifies its linked list while being iterated here
4067
        // in parallel. This design allows for lock-free
4068
        // register_task/unregister_task for loops running in parallel
4069
        // in different threads (the general case).
4070
0
        _PyEval_StopTheWorld(interp);
4071
0
        int ret = add_tasks_interp(interp, (PyListObject *)tasks);
4072
0
        _PyEval_StartTheWorld(interp);
4073
0
        if (ret < 0) {
4074
            // call any escaping calls after starting the world to avoid any deadlocks.
4075
0
            Py_DECREF(tasks);
4076
0
            Py_DECREF(loop);
4077
0
            return NULL;
4078
0
        }
4079
0
    }
4080
4081
    // All the tasks are now in the list, now filter the tasks which are done
4082
0
    PyObject *res = PySet_New(NULL);
4083
0
    if (res == NULL) {
4084
0
        Py_DECREF(tasks);
4085
0
        Py_DECREF(loop);
4086
0
        return NULL;
4087
0
    }
4088
4089
0
    for (Py_ssize_t i = 0; i < PyList_GET_SIZE(tasks); i++) {
4090
0
        PyObject *task = PyList_GET_ITEM(tasks, i);
4091
0
        if (add_one_task(state, res, task, loop) < 0) {
4092
0
            Py_DECREF(res);
4093
0
            Py_DECREF(tasks);
4094
0
            Py_DECREF(loop);
4095
0
            return NULL;
4096
0
        }
4097
0
    }
4098
4099
0
    Py_DECREF(tasks);
4100
0
    Py_DECREF(loop);
4101
0
    return res;
4102
0
}
4103
4104
/*[clinic input]
4105
_asyncio.future_add_to_awaited_by
4106
4107
    fut: object
4108
    waiter: object
4109
    /
4110
4111
Record that `fut` is awaited on by `waiter`.
4112
4113
[clinic start generated code]*/
4114
4115
static PyObject *
4116
_asyncio_future_add_to_awaited_by_impl(PyObject *module, PyObject *fut,
4117
                                       PyObject *waiter)
4118
/*[clinic end generated code: output=0ab9a1a63389e4df input=06e6eaac51f532b9]*/
4119
0
{
4120
0
    asyncio_state *state = get_asyncio_state(module);
4121
0
    if (TaskOrFuture_Check(state, fut) && TaskOrFuture_Check(state, waiter)) {
4122
0
        int res;
4123
0
        Py_BEGIN_CRITICAL_SECTION(fut);
4124
0
        res = future_awaited_by_add(state, (FutureObj *)fut, waiter);
4125
0
        Py_END_CRITICAL_SECTION();
4126
0
        if (res) {
4127
0
            return NULL;
4128
0
        }
4129
0
    }
4130
0
    Py_RETURN_NONE;
4131
0
}
4132
4133
/*[clinic input]
4134
_asyncio.future_discard_from_awaited_by
4135
4136
    fut: object
4137
    waiter: object
4138
    /
4139
4140
[clinic start generated code]*/
4141
4142
static PyObject *
4143
_asyncio_future_discard_from_awaited_by_impl(PyObject *module, PyObject *fut,
4144
                                             PyObject *waiter)
4145
/*[clinic end generated code: output=a03b0b4323b779de input=3833f7639e88e483]*/
4146
0
{
4147
0
    asyncio_state *state = get_asyncio_state(module);
4148
0
    if (TaskOrFuture_Check(state, fut) && TaskOrFuture_Check(state, waiter)) {
4149
0
        int res;
4150
0
        Py_BEGIN_CRITICAL_SECTION(fut);
4151
0
        res = future_awaited_by_discard(state, (FutureObj *)fut, waiter);
4152
0
        Py_END_CRITICAL_SECTION();
4153
0
        if (res) {
4154
0
            return NULL;
4155
0
        }
4156
0
    }
4157
0
    Py_RETURN_NONE;
4158
0
}
4159
4160
static int
4161
module_traverse(PyObject *mod, visitproc visit, void *arg)
4162
0
{
4163
0
    asyncio_state *state = get_asyncio_state(mod);
4164
4165
0
    Py_VISIT(state->FutureIterType);
4166
0
    Py_VISIT(state->TaskStepMethWrapper_Type);
4167
0
    Py_VISIT(state->FutureType);
4168
0
    Py_VISIT(state->TaskType);
4169
4170
0
    Py_VISIT(state->asyncio_mod);
4171
0
    Py_VISIT(state->traceback_extract_stack);
4172
0
    Py_VISIT(state->asyncio_future_repr_func);
4173
0
    Py_VISIT(state->asyncio_get_event_loop);
4174
0
    Py_VISIT(state->asyncio_iscoroutine_func);
4175
0
    Py_VISIT(state->asyncio_task_get_stack_func);
4176
0
    Py_VISIT(state->asyncio_task_print_stack_func);
4177
0
    Py_VISIT(state->asyncio_task_repr_func);
4178
0
    Py_VISIT(state->asyncio_InvalidStateError);
4179
0
    Py_VISIT(state->asyncio_CancelledError);
4180
4181
0
    Py_VISIT(state->non_asyncio_tasks);
4182
0
    Py_VISIT(state->non_asyncio_eager_tasks);
4183
0
    Py_VISIT(state->iscoroutine_typecache);
4184
4185
0
    Py_VISIT(state->context_kwname);
4186
4187
0
    return 0;
4188
0
}
4189
4190
static int
4191
module_clear(PyObject *mod)
4192
0
{
4193
0
    asyncio_state *state = get_asyncio_state(mod);
4194
4195
0
    Py_CLEAR(state->FutureIterType);
4196
0
    Py_CLEAR(state->TaskStepMethWrapper_Type);
4197
0
    Py_CLEAR(state->FutureType);
4198
0
    Py_CLEAR(state->TaskType);
4199
4200
0
    Py_CLEAR(state->asyncio_mod);
4201
0
    Py_CLEAR(state->traceback_extract_stack);
4202
0
    Py_CLEAR(state->asyncio_future_repr_func);
4203
0
    Py_CLEAR(state->asyncio_get_event_loop);
4204
0
    Py_CLEAR(state->asyncio_iscoroutine_func);
4205
0
    Py_CLEAR(state->asyncio_task_get_stack_func);
4206
0
    Py_CLEAR(state->asyncio_task_print_stack_func);
4207
0
    Py_CLEAR(state->asyncio_task_repr_func);
4208
0
    Py_CLEAR(state->asyncio_InvalidStateError);
4209
0
    Py_CLEAR(state->asyncio_CancelledError);
4210
4211
0
    Py_CLEAR(state->non_asyncio_tasks);
4212
0
    Py_CLEAR(state->non_asyncio_eager_tasks);
4213
0
    Py_CLEAR(state->iscoroutine_typecache);
4214
4215
0
    Py_CLEAR(state->context_kwname);
4216
    // Clear the ref to running loop so that finalizers can run early.
4217
    // If there are other running loops in different threads,
4218
    // those get cleared in PyThreadState_Clear.
4219
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
4220
0
    Py_CLEAR(ts->asyncio_running_loop);
4221
0
    Py_CLEAR(ts->asyncio_running_task);
4222
4223
0
    return 0;
4224
0
}
4225
4226
static void
4227
module_free(void *mod)
4228
0
{
4229
0
    (void)module_clear((PyObject *)mod);
4230
0
}
4231
4232
static int
4233
module_init(asyncio_state *state)
4234
0
{
4235
0
    PyObject *module = NULL;
4236
4237
0
    state->asyncio_mod = PyImport_ImportModule("asyncio");
4238
0
    if (state->asyncio_mod == NULL) {
4239
0
        goto fail;
4240
0
    }
4241
4242
0
    state->iscoroutine_typecache = PySet_New(NULL);
4243
0
    if (state->iscoroutine_typecache == NULL) {
4244
0
        goto fail;
4245
0
    }
4246
4247
0
    state->context_kwname = Py_BuildValue("(s)", "context");
4248
0
    if (state->context_kwname == NULL) {
4249
0
        goto fail;
4250
0
    }
4251
4252
0
#define WITH_MOD(NAME) \
4253
0
    Py_CLEAR(module); \
4254
0
    module = PyImport_ImportModule(NAME); \
4255
0
    if (module == NULL) { \
4256
0
        goto fail; \
4257
0
    }
4258
4259
0
#define GET_MOD_ATTR(VAR, NAME) \
4260
0
    VAR = PyObject_GetAttrString(module, NAME); \
4261
0
    if (VAR == NULL) { \
4262
0
        goto fail; \
4263
0
    }
4264
4265
0
    WITH_MOD("asyncio.events")
4266
0
    GET_MOD_ATTR(state->asyncio_get_event_loop, "_get_event_loop")
4267
4268
0
    WITH_MOD("asyncio.base_futures")
4269
0
    GET_MOD_ATTR(state->asyncio_future_repr_func, "_future_repr")
4270
4271
0
    WITH_MOD("asyncio.exceptions")
4272
0
    GET_MOD_ATTR(state->asyncio_InvalidStateError, "InvalidStateError")
4273
0
    GET_MOD_ATTR(state->asyncio_CancelledError, "CancelledError")
4274
4275
0
    WITH_MOD("asyncio.base_tasks")
4276
0
    GET_MOD_ATTR(state->asyncio_task_repr_func, "_task_repr")
4277
0
    GET_MOD_ATTR(state->asyncio_task_get_stack_func, "_task_get_stack")
4278
0
    GET_MOD_ATTR(state->asyncio_task_print_stack_func, "_task_print_stack")
4279
4280
0
    WITH_MOD("asyncio.coroutines")
4281
0
    GET_MOD_ATTR(state->asyncio_iscoroutine_func, "iscoroutine")
4282
4283
0
    WITH_MOD("traceback")
4284
0
    GET_MOD_ATTR(state->traceback_extract_stack, "extract_stack")
4285
4286
0
    PyObject *weak_set;
4287
0
    WITH_MOD("weakref")
4288
0
    GET_MOD_ATTR(weak_set, "WeakSet");
4289
0
    state->non_asyncio_tasks = PyObject_CallNoArgs(weak_set);
4290
0
    Py_CLEAR(weak_set);
4291
0
    if (state->non_asyncio_tasks == NULL) {
4292
0
        goto fail;
4293
0
    }
4294
4295
0
    state->non_asyncio_eager_tasks = PySet_New(NULL);
4296
0
    if (state->non_asyncio_eager_tasks == NULL) {
4297
0
        goto fail;
4298
0
    }
4299
4300
0
    state->debug_offsets = &_Py_AsyncioDebug;
4301
4302
0
    Py_DECREF(module);
4303
0
    return 0;
4304
4305
0
fail:
4306
0
    Py_CLEAR(module);
4307
0
    return -1;
4308
4309
0
#undef WITH_MOD
4310
0
#undef GET_MOD_ATTR
4311
0
}
4312
4313
PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
4314
4315
static PyMethodDef asyncio_methods[] = {
4316
    _ASYNCIO_CURRENT_TASK_METHODDEF
4317
    _ASYNCIO_GET_EVENT_LOOP_METHODDEF
4318
    _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
4319
    _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
4320
    _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
4321
    _ASYNCIO__REGISTER_TASK_METHODDEF
4322
    _ASYNCIO__REGISTER_EAGER_TASK_METHODDEF
4323
    _ASYNCIO__UNREGISTER_TASK_METHODDEF
4324
    _ASYNCIO__UNREGISTER_EAGER_TASK_METHODDEF
4325
    _ASYNCIO__ENTER_TASK_METHODDEF
4326
    _ASYNCIO__LEAVE_TASK_METHODDEF
4327
    _ASYNCIO__SWAP_CURRENT_TASK_METHODDEF
4328
    _ASYNCIO_ALL_TASKS_METHODDEF
4329
    _ASYNCIO_FUTURE_ADD_TO_AWAITED_BY_METHODDEF
4330
    _ASYNCIO_FUTURE_DISCARD_FROM_AWAITED_BY_METHODDEF
4331
    {NULL, NULL}
4332
};
4333
4334
static int
4335
module_exec(PyObject *mod)
4336
0
{
4337
0
    asyncio_state *state = get_asyncio_state(mod);
4338
4339
4340
0
#define CREATE_TYPE(m, tp, spec, base)                                  \
4341
0
    do {                                                                \
4342
0
        tp = (PyTypeObject *)PyType_FromMetaclass(NULL, m, spec,        \
4343
0
                                                  (PyObject *)base);    \
4344
0
        if (tp == NULL) {                                               \
4345
0
            return -1;                                                  \
4346
0
        }                                                               \
4347
0
    } while (0)
4348
4349
0
    CREATE_TYPE(mod, state->TaskStepMethWrapper_Type, &TaskStepMethWrapper_spec, NULL);
4350
0
    CREATE_TYPE(mod, state->FutureIterType, &FutureIter_spec, NULL);
4351
0
    CREATE_TYPE(mod, state->FutureType, &Future_spec, NULL);
4352
0
    CREATE_TYPE(mod, state->TaskType, &Task_spec, state->FutureType);
4353
4354
0
#undef CREATE_TYPE
4355
4356
0
    if (PyModule_AddType(mod, state->FutureType) < 0) {
4357
0
        return -1;
4358
0
    }
4359
4360
0
    if (PyModule_AddType(mod, state->TaskType) < 0) {
4361
0
        return -1;
4362
0
    }
4363
    // Must be done after types are added to avoid a circular dependency
4364
0
    if (module_init(state) < 0) {
4365
0
        return -1;
4366
0
    }
4367
4368
0
    return 0;
4369
0
}
4370
4371
static struct PyModuleDef_Slot module_slots[] = {
4372
    _Py_ABI_SLOT,
4373
    {Py_mod_exec, module_exec},
4374
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
4375
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
4376
    {0, NULL},
4377
};
4378
4379
static struct PyModuleDef _asynciomodule = {
4380
    .m_base = PyModuleDef_HEAD_INIT,
4381
    .m_name = "_asyncio",
4382
    .m_doc = module_doc,
4383
    .m_size = sizeof(asyncio_state),
4384
    .m_methods = asyncio_methods,
4385
    .m_slots = module_slots,
4386
    .m_traverse = module_traverse,
4387
    .m_clear = module_clear,
4388
    .m_free = module_free,
4389
};
4390
4391
PyMODINIT_FUNC
4392
PyInit__asyncio(void)
4393
0
{
4394
0
    return PyModuleDef_Init(&_asynciomodule);
4395
0
}