Coverage Report

Created: 2026-05-30 06:18

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