Coverage Report

Created: 2026-06-21 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Modules/_asynciomodule.c
Line
Count
Source
1
#ifndef Py_BUILD_CORE_BUILTIN
2
#  define Py_BUILD_CORE_MODULE 1
3
#endif
4
5
#include "Python.h"
6
#include "pycore_freelist.h"      // _Py_FREELIST_POP()
7
#include "pycore_genobject.h"
8
#include "pycore_llist.h"         // struct llist_node
9
#include "pycore_list.h"          // _PyList_AppendTakeRef()
10
#include "pycore_modsupport.h"    // _PyArg_CheckPositional()
11
#include "pycore_moduleobject.h"  // _PyModule_GetState()
12
#include "pycore_object.h"        // _PyObject_SetMaybeWeakref
13
#include "pycore_pylifecycle.h"   // _Py_IsInterpreterFinalizing()
14
#include "pycore_pystate.h"       // _PyThreadState_GET()
15
#include "pycore_runtime_init.h"  // _Py_ID()
16
#include "pycore_tuple.h"         // _PyTuple_FromPair
17
18
#include <stddef.h>               // offsetof()
19
20
21
/*[clinic input]
22
module _asyncio
23
[clinic start generated code]*/
24
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
25
26
typedef enum {
27
    STATE_PENDING,
28
    STATE_CANCELLED,
29
    STATE_FINISHED
30
} fut_state;
31
32
#define FutureObj_HEAD(prefix)                                              \
33
    PyObject_HEAD                                                           \
34
    PyObject *prefix##_loop;                                                \
35
    PyObject *prefix##_callback0;                                           \
36
    PyObject *prefix##_context0;                                            \
37
    PyObject *prefix##_callbacks;                                           \
38
    PyObject *prefix##_exception;                                           \
39
    PyObject *prefix##_exception_tb;                                        \
40
    PyObject *prefix##_result;                                              \
41
    PyObject *prefix##_source_tb;                                           \
42
    PyObject *prefix##_cancel_msg;                                          \
43
    PyObject *prefix##_cancelled_exc;                                       \
44
    PyObject *prefix##_awaited_by;                                          \
45
    fut_state prefix##_state;                                               \
46
    /* Used by profilers to make traversing the stack from an external      \
47
       process faster. */                                                   \
48
    char prefix##_is_task;                                                  \
49
    char prefix##_awaited_by_is_set;                                        \
50
    /* These bitfields need to be at the end of the struct                  \
51
       so that these and bitfields from TaskObj are contiguous.             \
52
    */                                                                      \
53
    unsigned prefix##_log_tb: 1;                                            \
54
    unsigned prefix##_blocking: 1;                                          \
55
56
typedef struct {
57
    FutureObj_HEAD(fut)
58
} FutureObj;
59
60
typedef struct TaskObj {
61
    FutureObj_HEAD(task)
62
    unsigned task_must_cancel: 1;
63
    unsigned task_log_destroy_pending: 1;
64
    int task_num_cancels_requested;
65
    PyObject *task_fut_waiter;
66
    PyObject *task_coro;
67
    PyObject *task_name;
68
    PyObject *task_context;
69
    struct llist_node task_node;
70
#ifdef Py_GIL_DISABLED
71
    // thread id of the thread where this task was created
72
    uintptr_t task_tid;
73
#endif
74
} TaskObj;
75
76
typedef struct {
77
    PyObject_HEAD
78
    TaskObj *sw_task;
79
    PyObject *sw_arg;
80
} TaskStepMethWrapper;
81
82
0
#define Future_CheckExact(state, obj) Py_IS_TYPE(obj, state->FutureType)
83
0
#define Task_CheckExact(state, obj) Py_IS_TYPE(obj, state->TaskType)
84
85
#define Future_Check(state, obj)                        \
86
    (Future_CheckExact(state, obj)                      \
87
     || PyObject_TypeCheck(obj, state->FutureType))
88
89
#define Task_Check(state, obj)                          \
90
0
    (Task_CheckExact(state, obj)                        \
91
0
     || PyObject_TypeCheck(obj, state->TaskType))
92
93
// This macro is optimized to quickly return for native Future *or* Task
94
// objects by inlining fast "exact" checks to be called first.
95
#define TaskOrFuture_Check(state, obj)                  \
96
0
    (Task_CheckExact(state, obj)                        \
97
0
     || Future_CheckExact(state, obj)                   \
98
0
     || PyObject_TypeCheck(obj, state->FutureType)      \
99
0
     || PyObject_TypeCheck(obj, state->TaskType))
100
101
typedef struct _Py_AsyncioModuleDebugOffsets {
102
    struct _asyncio_task_object {
103
        uint64_t size;
104
        uint64_t task_name;
105
        uint64_t task_awaited_by;
106
        uint64_t task_is_task;
107
        uint64_t task_awaited_by_is_set;
108
        uint64_t task_coro;
109
        uint64_t task_node;
110
    } asyncio_task_object;
111
    struct _asyncio_interpreter_state {
112
        uint64_t size;
113
        uint64_t asyncio_tasks_head;
114
    } asyncio_interpreter_state;
115
    struct _asyncio_thread_state {
116
        uint64_t size;
117
        uint64_t asyncio_running_loop;
118
        uint64_t asyncio_running_task;
119
        uint64_t asyncio_tasks_head;
120
    } asyncio_thread_state;
121
} Py_AsyncioModuleDebugOffsets;
122
123
GENERATE_DEBUG_SECTION(AsyncioDebug, Py_AsyncioModuleDebugOffsets _Py_AsyncioDebug)
124
    = {.asyncio_task_object = {
125
           .size = sizeof(TaskObj),
126
           .task_name = offsetof(TaskObj, task_name),
127
           .task_awaited_by = offsetof(TaskObj, task_awaited_by),
128
           .task_is_task = offsetof(TaskObj, task_is_task),
129
           .task_awaited_by_is_set = offsetof(TaskObj, task_awaited_by_is_set),
130
           .task_coro = offsetof(TaskObj, task_coro),
131
           .task_node = offsetof(TaskObj, task_node),
132
       },
133
       .asyncio_interpreter_state = {
134
            .size = sizeof(PyInterpreterState),
135
            .asyncio_tasks_head = offsetof(PyInterpreterState, asyncio_tasks_head),
136
       },
137
       .asyncio_thread_state = {
138
           .size = sizeof(_PyThreadStateImpl),
139
           .asyncio_running_loop = offsetof(_PyThreadStateImpl, asyncio_running_loop),
140
           .asyncio_running_task = offsetof(_PyThreadStateImpl, asyncio_running_task),
141
           .asyncio_tasks_head = offsetof(_PyThreadStateImpl, asyncio_tasks_head),
142
       }};
143
144
/* State of the _asyncio module */
145
typedef struct {
146
    PyTypeObject *FutureIterType;
147
    PyTypeObject *TaskStepMethWrapper_Type;
148
    PyTypeObject *FutureType;
149
    PyTypeObject *TaskType;
150
151
    PyObject *asyncio_mod;
152
    PyObject *context_kwname;
153
154
    /* WeakSet containing scheduled 3rd party tasks which don't
155
       inherit from native asyncio.Task */
156
    PyObject *non_asyncio_tasks;
157
158
    /* Set containing all 3rd party eagerly executing tasks which don't
159
       inherit from native asyncio.Task */
160
    PyObject *non_asyncio_eager_tasks;
161
162
    /* An isinstance type cache for the 'is_coroutine()' function. */
163
    PyObject *iscoroutine_typecache;
164
165
    /* Imports from asyncio.events. */
166
    PyObject *asyncio_get_event_loop_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
0
{
198
0
    asyncio_state *state = _PyModule_GetState(mod);
199
0
    assert(state != NULL);
200
0
    return state;
201
0
}
202
203
static inline asyncio_state *
204
get_asyncio_state_by_cls(PyTypeObject *cls)
205
0
{
206
0
    asyncio_state *state = (asyncio_state *)_PyType_GetModuleState(cls);
207
0
    assert(state != NULL);
208
0
    return state;
209
0
}
210
211
static struct PyModuleDef _asynciomodule;
212
213
static inline asyncio_state *
214
get_asyncio_state_by_def(PyObject *self)
215
0
{
216
0
    PyTypeObject *tp = Py_TYPE(self);
217
0
    PyObject *mod = PyType_GetModuleByDef(tp, &_asynciomodule);
218
0
    assert(mod != NULL);
219
0
    return get_asyncio_state(mod);
220
0
}
221
222
#include "clinic/_asynciomodule.c.h"
223
224
225
/*[clinic input]
226
class _asyncio.Future "FutureObj *" "&Future_Type"
227
[clinic start generated code]*/
228
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
229
230
231
/* Get FutureIter from Future */
232
static PyObject * future_new_iter(PyObject *);
233
234
static PyObject *
235
task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *result);
236
static void unregister_task(TaskObj *task);
237
238
static void
239
clear_task_coro(TaskObj *task)
240
0
{
241
0
    Py_CLEAR(task->task_coro);
242
0
}
243
244
245
static void
246
set_task_coro(TaskObj *task, PyObject *coro)
247
0
{
248
0
    assert(coro != NULL);
249
0
    Py_INCREF(coro);
250
0
    Py_XSETREF(task->task_coro, coro);
251
0
}
252
253
254
static int
255
_is_coroutine(asyncio_state *state, PyObject *coro)
256
0
{
257
    /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
258
       to check if it's another coroutine flavour.
259
260
       Do this check after 'future_init()'; in case we need to raise
261
       an error, __del__ needs a properly initialized object.
262
    */
263
0
    PyObject *res = PyObject_CallOneArg(state->asyncio_iscoroutine_func, coro);
264
0
    if (res == NULL) {
265
0
        return -1;
266
0
    }
267
268
0
    int is_res_true = PyObject_IsTrue(res);
269
0
    Py_DECREF(res);
270
0
    if (is_res_true <= 0) {
271
0
        return is_res_true;
272
0
    }
273
274
0
    if (PySet_GET_SIZE(state->iscoroutine_typecache) < 100) {
275
        /* Just in case we don't want to cache more than 100
276
           positive types.  That shouldn't ever happen, unless
277
           someone stressing the system on purpose.
278
        */
279
0
        if (PySet_Add(state->iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
280
0
            return -1;
281
0
        }
282
0
    }
283
284
0
    return 1;
285
0
}
286
287
288
static inline int
289
is_coroutine(asyncio_state *state, PyObject *coro)
290
0
{
291
0
    if (PyCoro_CheckExact(coro)) {
292
0
        return 1;
293
0
    }
294
295
    /* Check if `type(coro)` is in the cache.
296
       Caching makes is_coroutine() function almost as fast as
297
       PyCoro_CheckExact() for non-native coroutine-like objects
298
       (like coroutines compiled with Cython).
299
300
       asyncio.iscoroutine() has its own type caching mechanism.
301
       This cache allows us to avoid the cost of even calling
302
       a pure-Python function in 99.9% cases.
303
    */
304
0
    int has_it = PySet_Contains(
305
0
        state->iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
306
0
    if (has_it == 0) {
307
        /* type(coro) is not in iscoroutine_typecache */
308
0
        return _is_coroutine(state, coro);
309
0
    }
310
311
    /* either an error has occurred or
312
       type(coro) is in iscoroutine_typecache
313
    */
314
0
    return has_it;
315
0
}
316
317
318
static PyObject *
319
get_future_loop(asyncio_state *state, PyObject *fut)
320
0
{
321
    /* Implementation of `asyncio.futures._get_loop` */
322
323
0
    PyObject *getloop;
324
325
0
    if (Future_CheckExact(state, fut) || Task_CheckExact(state, fut)) {
326
0
        PyObject *loop = ((FutureObj *)fut)->fut_loop;
327
0
        return Py_NewRef(loop);
328
0
    }
329
330
0
    if (PyObject_GetOptionalAttr(fut, &_Py_ID(get_loop), &getloop) < 0) {
331
0
        return NULL;
332
0
    }
333
0
    if (getloop != NULL) {
334
0
        PyObject *res = PyObject_CallNoArgs(getloop);
335
0
        Py_DECREF(getloop);
336
0
        return res;
337
0
    }
338
339
0
    return PyObject_GetAttr(fut, &_Py_ID(_loop));
340
0
}
341
342
static PyObject *
343
get_event_loop(asyncio_state *state)
344
0
{
345
0
    PyObject *loop;
346
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,
1746
    PyDoc_STR("Futures are generic over the type of their results")},
1747
    {NULL, NULL}        /* Sentinel */
1748
};
1749
1750
static PyGetSetDef FutureType_getsetlist[] = {
1751
    _ASYNCIO_FUTURE__STATE_GETSETDEF
1752
    _ASYNCIO_FUTURE__ASYNCIO_FUTURE_BLOCKING_GETSETDEF
1753
    _ASYNCIO_FUTURE__LOOP_GETSETDEF
1754
    _ASYNCIO_FUTURE__CALLBACKS_GETSETDEF
1755
    _ASYNCIO_FUTURE__RESULT_GETSETDEF
1756
    _ASYNCIO_FUTURE__EXCEPTION_GETSETDEF
1757
    _ASYNCIO_FUTURE__LOG_TRACEBACK_GETSETDEF
1758
    _ASYNCIO_FUTURE__SOURCE_TRACEBACK_GETSETDEF
1759
    _ASYNCIO_FUTURE__CANCEL_MESSAGE_GETSETDEF
1760
    _ASYNCIO_FUTURE__ASYNCIO_AWAITED_BY_GETSETDEF
1761
    {NULL} /* Sentinel */
1762
};
1763
1764
static void FutureObj_dealloc(PyObject *self);
1765
1766
static PyType_Slot Future_slots[] = {
1767
    {Py_tp_dealloc, FutureObj_dealloc},
1768
    {Py_tp_repr, FutureObj_repr},
1769
    {Py_tp_doc, (void *)_asyncio_Future___init____doc__},
1770
    {Py_tp_traverse, FutureObj_traverse},
1771
    {Py_tp_clear, FutureObj_clear},
1772
    {Py_tp_iter, future_new_iter},
1773
    {Py_tp_methods, FutureType_methods},
1774
    {Py_tp_getset, FutureType_getsetlist},
1775
    {Py_tp_init, _asyncio_Future___init__},
1776
    {Py_tp_new, PyType_GenericNew},
1777
    {Py_tp_finalize, FutureObj_finalize},
1778
1779
    // async slots
1780
    {Py_am_await, future_new_iter},
1781
    {0, NULL},
1782
};
1783
1784
static PyType_Spec Future_spec = {
1785
    .name = "_asyncio.Future",
1786
    .basicsize = sizeof(FutureObj),
1787
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
1788
              Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT |
1789
              Py_TPFLAGS_MANAGED_WEAKREF),
1790
    .slots = Future_slots,
1791
};
1792
1793
static void
1794
FutureObj_dealloc(PyObject *self)
1795
0
{
1796
0
    if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1797
        // resurrected.
1798
0
        return;
1799
0
    }
1800
1801
0
    PyTypeObject *tp = Py_TYPE(self);
1802
0
    PyObject_GC_UnTrack(self);
1803
1804
0
    PyObject_ClearWeakRefs(self);
1805
1806
0
    (void)FutureObj_clear(self);
1807
0
    tp->tp_free(self);
1808
0
    Py_DECREF(tp);
1809
0
}
1810
1811
1812
/*********************** Future Iterator **************************/
1813
1814
typedef struct futureiterobject {
1815
    PyObject_HEAD
1816
    FutureObj *future;
1817
} futureiterobject;
1818
1819
1820
static void
1821
FutureIter_dealloc(PyObject *it)
1822
0
{
1823
0
    PyTypeObject *tp = Py_TYPE(it);
1824
1825
0
    assert(_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE));
1826
1827
0
    PyObject_GC_UnTrack(it);
1828
0
    tp->tp_clear(it);
1829
1830
0
    if (!_Py_FREELIST_PUSH(futureiters, it, Py_futureiters_MAXFREELIST)) {
1831
0
        PyObject_GC_Del(it);
1832
0
        Py_DECREF(tp);
1833
0
    }
1834
0
}
1835
1836
static PySendResult
1837
FutureIter_am_send_lock_held(futureiterobject *it, PyObject **result)
1838
0
{
1839
0
    PyObject *res;
1840
0
    FutureObj *fut = it->future;
1841
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut);
1842
1843
0
    *result = NULL;
1844
1845
0
    if (fut->fut_state == STATE_PENDING) {
1846
0
        if (!fut->fut_blocking) {
1847
0
            fut->fut_blocking = 1;
1848
0
            *result = Py_NewRef(fut);
1849
0
            return PYGEN_NEXT;
1850
0
        }
1851
0
        PyErr_SetString(PyExc_RuntimeError,
1852
0
                        "await wasn't used with future");
1853
0
        return PYGEN_ERROR;
1854
0
    }
1855
1856
0
    res = _asyncio_Future_result_impl(fut);
1857
0
    if (res != NULL) {
1858
0
        *result = res;
1859
0
        return PYGEN_RETURN;
1860
0
    }
1861
1862
0
    return PYGEN_ERROR;
1863
0
}
1864
1865
static PySendResult
1866
FutureIter_am_send(PyObject *op,
1867
                   PyObject *Py_UNUSED(arg),
1868
                   PyObject **result)
1869
0
{
1870
0
    futureiterobject *it = (futureiterobject*)op;
1871
    /* arg is unused, see the comment on FutureIter_send for clarification */
1872
0
    PySendResult res;
1873
0
    Py_BEGIN_CRITICAL_SECTION(it->future);
1874
0
    res = FutureIter_am_send_lock_held(it, result);
1875
0
    Py_END_CRITICAL_SECTION();
1876
0
    return res;
1877
0
}
1878
1879
1880
static PyObject *
1881
FutureIter_iternext(PyObject *it)
1882
0
{
1883
0
    PyObject *result;
1884
0
    switch (FutureIter_am_send(it, Py_None, &result)) {
1885
0
        case PYGEN_RETURN:
1886
0
            (void)_PyGen_SetStopIterationValue(result);
1887
0
            Py_DECREF(result);
1888
0
            return NULL;
1889
0
        case PYGEN_NEXT:
1890
0
            return result;
1891
0
        case PYGEN_ERROR:
1892
0
            return NULL;
1893
0
        default:
1894
0
            Py_UNREACHABLE();
1895
0
    }
1896
0
}
1897
1898
static PyObject *
1899
FutureIter_send(PyObject *self, PyObject *unused)
1900
0
{
1901
    /* Future.__iter__ doesn't care about values that are pushed to the
1902
     * generator, it just returns self.result().
1903
     */
1904
0
    return FutureIter_iternext(self);
1905
0
}
1906
1907
static PyObject *
1908
FutureIter_throw(PyObject *op, PyObject *const *args, Py_ssize_t nargs)
1909
0
{
1910
0
    futureiterobject *self = (futureiterobject*)op;
1911
0
    PyObject *type, *val = NULL, *tb = NULL;
1912
0
    if (!_PyArg_CheckPositional("throw", nargs, 1, 3)) {
1913
0
        return NULL;
1914
0
    }
1915
0
    if (nargs > 1) {
1916
0
        if (PyErr_WarnEx(PyExc_DeprecationWarning,
1917
0
                            "the (type, exc, tb) signature of throw() is deprecated, "
1918
0
                            "use the single-arg signature instead.",
1919
0
                            1) < 0) {
1920
0
            return NULL;
1921
0
        }
1922
0
    }
1923
1924
0
    type = args[0];
1925
0
    if (nargs == 3) {
1926
0
        val = args[1];
1927
0
        tb = args[2];
1928
0
    }
1929
0
    else if (nargs == 2) {
1930
0
        val = args[1];
1931
0
    }
1932
1933
0
    if (val == Py_None) {
1934
0
        val = NULL;
1935
0
    }
1936
0
    if (tb == Py_None ) {
1937
0
        tb = NULL;
1938
0
    } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1939
0
        PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1940
0
        return NULL;
1941
0
    }
1942
1943
0
    Py_INCREF(type);
1944
0
    Py_XINCREF(val);
1945
0
    Py_XINCREF(tb);
1946
1947
0
    if (PyExceptionClass_Check(type)) {
1948
0
        PyErr_NormalizeException(&type, &val, &tb);
1949
        /* No need to call PyException_SetTraceback since we'll be calling
1950
           PyErr_Restore for `type`, `val`, and `tb`. */
1951
0
    } else if (PyExceptionInstance_Check(type)) {
1952
0
        if (val) {
1953
0
            PyErr_SetString(PyExc_TypeError,
1954
0
                            "instance exception may not have a separate value");
1955
0
            goto fail;
1956
0
        }
1957
0
        val = type;
1958
0
        type = PyExceptionInstance_Class(type);
1959
0
        Py_INCREF(type);
1960
0
        if (tb == NULL)
1961
0
            tb = PyException_GetTraceback(val);
1962
0
    } else {
1963
0
        PyErr_SetString(PyExc_TypeError,
1964
0
                        "exceptions must be classes deriving BaseException or "
1965
0
                        "instances of such a class");
1966
0
        goto fail;
1967
0
    }
1968
1969
0
    Py_CLEAR(self->future);
1970
1971
0
    PyErr_Restore(type, val, tb);
1972
1973
0
    return NULL;
1974
1975
0
  fail:
1976
0
    Py_DECREF(type);
1977
0
    Py_XDECREF(val);
1978
0
    Py_XDECREF(tb);
1979
0
    return NULL;
1980
0
}
1981
1982
static int
1983
FutureIter_clear(PyObject *op)
1984
0
{
1985
0
    futureiterobject *it = (futureiterobject*)op;
1986
0
    Py_CLEAR(it->future);
1987
0
    return 0;
1988
0
}
1989
1990
static PyObject *
1991
FutureIter_close(PyObject *self, PyObject *arg)
1992
0
{
1993
0
    (void)FutureIter_clear(self);
1994
0
    Py_RETURN_NONE;
1995
0
}
1996
1997
static int
1998
FutureIter_traverse(PyObject *op, visitproc visit, void *arg)
1999
0
{
2000
0
    futureiterobject *it = (futureiterobject*)op;
2001
0
    Py_VISIT(Py_TYPE(it));
2002
0
    Py_VISIT(it->future);
2003
0
    return 0;
2004
0
}
2005
2006
static PyMethodDef FutureIter_methods[] = {
2007
    {"send",  FutureIter_send, METH_O, NULL},
2008
    {"throw", _PyCFunction_CAST(FutureIter_throw), METH_FASTCALL, NULL},
2009
    {"close", FutureIter_close, METH_NOARGS, NULL},
2010
    {NULL, NULL}        /* Sentinel */
2011
};
2012
2013
static PyType_Slot FutureIter_slots[] = {
2014
    {Py_tp_dealloc, FutureIter_dealloc},
2015
    {Py_tp_getattro, PyObject_GenericGetAttr},
2016
    {Py_tp_traverse, FutureIter_traverse},
2017
    {Py_tp_clear, FutureIter_clear},
2018
    {Py_tp_iter, PyObject_SelfIter},
2019
    {Py_tp_iternext, FutureIter_iternext},
2020
    {Py_tp_methods, FutureIter_methods},
2021
2022
    // async methods
2023
    {Py_am_send, FutureIter_am_send},
2024
    {0, NULL},
2025
};
2026
2027
static PyType_Spec FutureIter_spec = {
2028
    .name = "_asyncio.FutureIter",
2029
    .basicsize = sizeof(futureiterobject),
2030
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2031
              Py_TPFLAGS_IMMUTABLETYPE),
2032
    .slots = FutureIter_slots,
2033
};
2034
2035
static PyObject *
2036
future_new_iter(PyObject *fut)
2037
0
{
2038
0
    futureiterobject *it;
2039
2040
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)fut);
2041
0
    ENSURE_FUTURE_ALIVE(state, fut)
2042
2043
0
    it = _Py_FREELIST_POP(futureiterobject, futureiters);
2044
0
    if (it == NULL) {
2045
0
        it = PyObject_GC_New(futureiterobject, state->FutureIterType);
2046
0
        if (it == NULL) {
2047
0
            return NULL;
2048
0
        }
2049
0
    }
2050
2051
0
    it->future = (FutureObj*)Py_NewRef(fut);
2052
0
    PyObject_GC_Track(it);
2053
0
    return (PyObject*)it;
2054
0
}
2055
2056
2057
/*********************** Task **************************/
2058
2059
2060
/*[clinic input]
2061
class _asyncio.Task "TaskObj *" "&Task_Type"
2062
[clinic start generated code]*/
2063
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
2064
2065
static int task_call_step_soon(asyncio_state *state, TaskObj *, PyObject *);
2066
static PyObject *task_wakeup(PyObject *op, PyObject *arg);
2067
static PyObject *task_step(asyncio_state *, TaskObj *, PyObject *);
2068
static int task_eager_start(_PyThreadStateImpl *ts, asyncio_state *state, TaskObj *task);
2069
2070
/* ----- Task._step wrapper */
2071
2072
static int
2073
TaskStepMethWrapper_clear(PyObject *op)
2074
0
{
2075
0
    TaskStepMethWrapper *o = (TaskStepMethWrapper*)op;
2076
0
    Py_CLEAR(o->sw_task);
2077
0
    Py_CLEAR(o->sw_arg);
2078
0
    return 0;
2079
0
}
2080
2081
static void
2082
TaskStepMethWrapper_dealloc(PyObject *op)
2083
0
{
2084
0
    TaskStepMethWrapper *o = (TaskStepMethWrapper*)op;
2085
0
    PyTypeObject *tp = Py_TYPE(o);
2086
0
    PyObject_GC_UnTrack(o);
2087
0
    (void)TaskStepMethWrapper_clear(op);
2088
0
    Py_TYPE(o)->tp_free(o);
2089
0
    Py_DECREF(tp);
2090
0
}
2091
2092
static PyObject *
2093
TaskStepMethWrapper_call(PyObject *op,
2094
                         PyObject *args, PyObject *kwds)
2095
0
{
2096
0
    TaskStepMethWrapper *o = (TaskStepMethWrapper*)op;
2097
0
    if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
2098
0
        PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
2099
0
        return NULL;
2100
0
    }
2101
0
    if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
2102
0
        PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
2103
0
        return NULL;
2104
0
    }
2105
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)o);
2106
0
    PyObject *res;
2107
0
    Py_BEGIN_CRITICAL_SECTION(o->sw_task);
2108
0
    res = task_step(state, o->sw_task, o->sw_arg);
2109
0
    Py_END_CRITICAL_SECTION();
2110
0
    return res;
2111
0
}
2112
2113
static int
2114
TaskStepMethWrapper_traverse(PyObject *op,
2115
                             visitproc visit, void *arg)
2116
0
{
2117
0
    TaskStepMethWrapper *o = (TaskStepMethWrapper*)op;
2118
0
    Py_VISIT(Py_TYPE(o));
2119
0
    Py_VISIT(o->sw_task);
2120
0
    Py_VISIT(o->sw_arg);
2121
0
    return 0;
2122
0
}
2123
2124
static PyObject *
2125
TaskStepMethWrapper_get___self__(PyObject *op, void *Py_UNUSED(closure))
2126
0
{
2127
0
    TaskStepMethWrapper *o = (TaskStepMethWrapper*)op;
2128
0
    if (o->sw_task) {
2129
0
        return Py_NewRef(o->sw_task);
2130
0
    }
2131
0
    Py_RETURN_NONE;
2132
0
}
2133
2134
static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
2135
    {"__self__", TaskStepMethWrapper_get___self__, NULL, NULL},
2136
    {NULL} /* Sentinel */
2137
};
2138
2139
static PyType_Slot TaskStepMethWrapper_slots[] = {
2140
    {Py_tp_getset, TaskStepMethWrapper_getsetlist},
2141
    {Py_tp_dealloc, TaskStepMethWrapper_dealloc},
2142
    {Py_tp_call, TaskStepMethWrapper_call},
2143
    {Py_tp_getattro, PyObject_GenericGetAttr},
2144
    {Py_tp_traverse, TaskStepMethWrapper_traverse},
2145
    {Py_tp_clear, TaskStepMethWrapper_clear},
2146
    {0, NULL},
2147
};
2148
2149
static PyType_Spec TaskStepMethWrapper_spec = {
2150
    .name = "_asyncio.TaskStepMethWrapper",
2151
    .basicsize = sizeof(TaskStepMethWrapper),
2152
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2153
              Py_TPFLAGS_IMMUTABLETYPE),
2154
    .slots = TaskStepMethWrapper_slots,
2155
};
2156
2157
static PyObject *
2158
TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
2159
0
{
2160
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)task);
2161
0
    TaskStepMethWrapper *o;
2162
0
    o = PyObject_GC_New(TaskStepMethWrapper, state->TaskStepMethWrapper_Type);
2163
0
    if (o == NULL) {
2164
0
        return NULL;
2165
0
    }
2166
2167
0
    o->sw_task = (TaskObj*)Py_NewRef(task);
2168
0
    o->sw_arg = Py_XNewRef(arg);
2169
2170
0
    PyObject_GC_Track(o);
2171
0
    return (PyObject*) o;
2172
0
}
2173
2174
/* ----- Task._wakeup implementation */
2175
2176
static  PyMethodDef TaskWakeupDef = {
2177
    "task_wakeup",
2178
    task_wakeup,
2179
    METH_O,
2180
    NULL
2181
};
2182
2183
/* ----- Task introspection helpers */
2184
2185
static void
2186
register_task(_PyThreadStateImpl *ts, TaskObj *task)
2187
0
{
2188
0
    if (task->task_node.next != NULL) {
2189
        // already registered
2190
0
        assert(task->task_node.prev != NULL);
2191
0
        return;
2192
0
    }
2193
0
    struct llist_node *head = &ts->asyncio_tasks_head;
2194
0
    llist_insert_tail(head, &task->task_node);
2195
0
}
2196
2197
static inline void
2198
unregister_task_safe(TaskObj *task)
2199
0
{
2200
0
    if (task->task_node.next == NULL) {
2201
        // not registered
2202
0
        assert(task->task_node.prev == NULL);
2203
0
        return;
2204
0
    }
2205
0
    llist_remove(&task->task_node);
2206
0
}
2207
2208
static void
2209
unregister_task(TaskObj *task)
2210
0
{
2211
#ifdef Py_GIL_DISABLED
2212
    // check if we are in the same thread
2213
    // if so, we can avoid locking
2214
    if (task->task_tid == _Py_ThreadId()) {
2215
        unregister_task_safe(task);
2216
    }
2217
    else {
2218
        // we are in a different thread
2219
        // stop the world then check and remove the task
2220
        PyThreadState *tstate = _PyThreadState_GET();
2221
        _PyEval_StopTheWorld(tstate->interp);
2222
        unregister_task_safe(task);
2223
        _PyEval_StartTheWorld(tstate->interp);
2224
    }
2225
#else
2226
0
    unregister_task_safe(task);
2227
0
#endif
2228
0
}
2229
2230
static int
2231
enter_task(_PyThreadStateImpl *ts, PyObject *loop, PyObject *task)
2232
0
{
2233
0
    if (ts->asyncio_running_loop != loop) {
2234
0
        PyErr_Format(PyExc_RuntimeError, "loop %R is not the running loop", loop);
2235
0
        return -1;
2236
0
    }
2237
2238
0
    if (ts->asyncio_running_task != NULL) {
2239
0
        PyErr_Format(
2240
0
            PyExc_RuntimeError,
2241
0
            "Cannot enter into task %R while another " \
2242
0
            "task %R is being executed.",
2243
0
            task, ts->asyncio_running_task);
2244
0
        return -1;
2245
0
    }
2246
2247
0
    ts->asyncio_running_task = Py_NewRef(task);
2248
0
    return 0;
2249
0
}
2250
2251
static int
2252
leave_task(_PyThreadStateImpl *ts, PyObject *loop, PyObject *task)
2253
0
{
2254
0
    if (ts->asyncio_running_loop != loop) {
2255
0
        PyErr_Format(PyExc_RuntimeError, "loop %R is not the running loop", loop);
2256
0
        return -1;
2257
0
    }
2258
2259
0
    if (ts->asyncio_running_task != task) {
2260
0
        PyErr_Format(
2261
0
            PyExc_RuntimeError,
2262
0
            "Invalid attempt to leave task %R while " \
2263
0
            "task %R is entered.",
2264
0
            task, ts->asyncio_running_task ? ts->asyncio_running_task : Py_None);
2265
0
        return -1;
2266
0
    }
2267
0
    Py_CLEAR(ts->asyncio_running_task);
2268
0
    return 0;
2269
0
}
2270
2271
static PyObject *
2272
swap_current_task(_PyThreadStateImpl *ts, PyObject *loop, PyObject *task)
2273
0
{
2274
0
    if (ts->asyncio_running_loop != loop) {
2275
0
        PyErr_Format(PyExc_RuntimeError, "loop %R is not the running loop", loop);
2276
0
        return NULL;
2277
0
    }
2278
2279
    /* transfer ownership to avoid redundant ref counting */
2280
0
    PyObject *prev_task = ts->asyncio_running_task;
2281
0
    if (task != Py_None) {
2282
0
        ts->asyncio_running_task = Py_NewRef(task);
2283
0
    } else {
2284
0
        ts->asyncio_running_task = NULL;
2285
0
    }
2286
0
    if (prev_task == NULL) {
2287
0
        Py_RETURN_NONE;
2288
0
    }
2289
0
    return prev_task;
2290
0
}
2291
2292
/* ----- Task */
2293
2294
/*[clinic input]
2295
_asyncio.Task.__init__
2296
2297
    coro: object
2298
    *
2299
    loop: object = None
2300
    name: object = None
2301
    context: object = None
2302
    eager_start: bool = False
2303
2304
A coroutine wrapped in a Future.
2305
[clinic start generated code]*/
2306
2307
static int
2308
_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2309
                            PyObject *name, PyObject *context,
2310
                            int eager_start)
2311
/*[clinic end generated code: output=7aced2d27836f1a1 input=18e3f113a51b829d]*/
2312
0
{
2313
0
    if (future_init((FutureObj*)self, loop)) {
2314
0
        return -1;
2315
0
    }
2316
0
    self->task_is_task = 1;
2317
2318
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)self);
2319
0
    int is_coro = is_coroutine(state, coro);
2320
0
    if (is_coro == -1) {
2321
0
        return -1;
2322
0
    }
2323
0
    if (is_coro == 0) {
2324
0
        self->task_log_destroy_pending = 0;
2325
0
        PyErr_Format(PyExc_TypeError,
2326
0
                     "a coroutine was expected, got %R",
2327
0
                     coro);
2328
0
        return -1;
2329
0
    }
2330
2331
0
    if (context == Py_None) {
2332
0
        Py_XSETREF(self->task_context, PyContext_CopyCurrent());
2333
0
        if (self->task_context == NULL) {
2334
0
            return -1;
2335
0
        }
2336
0
    } else {
2337
0
        Py_XSETREF(self->task_context, Py_NewRef(context));
2338
0
    }
2339
2340
0
    Py_CLEAR(self->task_fut_waiter);
2341
#ifdef Py_GIL_DISABLED
2342
    self->task_tid = _Py_ThreadId();
2343
#endif
2344
0
    self->task_must_cancel = 0;
2345
0
    self->task_log_destroy_pending = 1;
2346
0
    self->task_num_cancels_requested = 0;
2347
0
    set_task_coro(self, coro);
2348
2349
0
    if (name == Py_None) {
2350
        // optimization: defer task name formatting
2351
        // store the task counter as PyLong in the name
2352
        // for deferred formatting in get_name
2353
#ifdef Py_GIL_DISABLED
2354
        unsigned long long counter = _Py_atomic_add_uint64(&state->task_name_counter, 1) + 1;
2355
#else
2356
0
        unsigned long long counter = ++state->task_name_counter;
2357
0
#endif
2358
0
        name = PyLong_FromUnsignedLongLong(counter);
2359
0
    } else if (!PyUnicode_CheckExact(name)) {
2360
0
        name = PyObject_Str(name);
2361
0
    } else {
2362
0
        Py_INCREF(name);
2363
0
    }
2364
0
    Py_XSETREF(self->task_name, name);
2365
0
    if (self->task_name == NULL) {
2366
0
        return -1;
2367
0
    }
2368
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
2369
0
    if (eager_start) {
2370
0
        PyObject *res = PyObject_CallMethodNoArgs(loop, &_Py_ID(is_running));
2371
0
        if (res == NULL) {
2372
0
            return -1;
2373
0
        }
2374
0
        int is_loop_running = Py_IsTrue(res);
2375
0
        Py_DECREF(res);
2376
0
        if (is_loop_running) {
2377
0
            if (task_eager_start(ts, state, self)) {
2378
0
                return -1;
2379
0
            }
2380
0
            return 0;
2381
0
        }
2382
0
    }
2383
2384
0
    if (task_call_step_soon(state, self, NULL)) {
2385
0
        return -1;
2386
0
    }
2387
#ifdef Py_GIL_DISABLED
2388
    // This is required so that _Py_TryIncref(self)
2389
    // works correctly in non-owning threads.
2390
    _PyObject_SetMaybeWeakref((PyObject *)self);
2391
#endif
2392
0
    register_task(ts, self);
2393
0
    return 0;
2394
0
}
2395
2396
static int
2397
TaskObj_clear(PyObject *op)
2398
0
{
2399
0
    TaskObj *task = (TaskObj*)op;
2400
0
    (void)FutureObj_clear(op);
2401
0
    clear_task_coro(task);
2402
0
    Py_CLEAR(task->task_context);
2403
0
    Py_CLEAR(task->task_name);
2404
0
    Py_CLEAR(task->task_fut_waiter);
2405
0
    return 0;
2406
0
}
2407
2408
static int
2409
TaskObj_traverse(PyObject *op, visitproc visit, void *arg)
2410
0
{
2411
0
    TaskObj *task = (TaskObj*)op;
2412
0
    Py_VISIT(Py_TYPE(task));
2413
0
    Py_VISIT(task->task_context);
2414
0
    Py_VISIT(task->task_coro);
2415
0
    Py_VISIT(task->task_name);
2416
0
    Py_VISIT(task->task_fut_waiter);
2417
0
    FutureObj *fut = (FutureObj *)task;
2418
0
    Py_VISIT(fut->fut_loop);
2419
0
    Py_VISIT(fut->fut_callback0);
2420
0
    Py_VISIT(fut->fut_context0);
2421
0
    Py_VISIT(fut->fut_callbacks);
2422
0
    Py_VISIT(fut->fut_result);
2423
0
    Py_VISIT(fut->fut_exception);
2424
0
    Py_VISIT(fut->fut_exception_tb);
2425
0
    Py_VISIT(fut->fut_source_tb);
2426
0
    Py_VISIT(fut->fut_cancel_msg);
2427
0
    Py_VISIT(fut->fut_cancelled_exc);
2428
0
    Py_VISIT(fut->fut_awaited_by);
2429
0
    return PyObject_VisitManagedDict((PyObject *)fut, visit, arg);
2430
0
}
2431
2432
/*[clinic input]
2433
@critical_section
2434
@getter
2435
_asyncio.Task._log_destroy_pending
2436
[clinic start generated code]*/
2437
2438
static PyObject *
2439
_asyncio_Task__log_destroy_pending_get_impl(TaskObj *self)
2440
/*[clinic end generated code: output=e6c2a47d029ac93b input=17127298cd4c720b]*/
2441
0
{
2442
0
    if (self->task_log_destroy_pending) {
2443
0
        Py_RETURN_TRUE;
2444
0
    }
2445
0
    else {
2446
0
        Py_RETURN_FALSE;
2447
0
    }
2448
0
}
2449
2450
/*[clinic input]
2451
@critical_section
2452
@setter
2453
_asyncio.Task._log_destroy_pending
2454
[clinic start generated code]*/
2455
2456
static int
2457
_asyncio_Task__log_destroy_pending_set_impl(TaskObj *self, PyObject *value)
2458
/*[clinic end generated code: output=7ebc030bb92ec5ce input=49b759c97d1216a4]*/
2459
0
{
2460
0
    if (value == NULL) {
2461
0
        PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2462
0
        return -1;
2463
0
    }
2464
0
    int is_true = PyObject_IsTrue(value);
2465
0
    if (is_true < 0) {
2466
0
        return -1;
2467
0
    }
2468
0
    self->task_log_destroy_pending = is_true;
2469
0
    return 0;
2470
0
}
2471
2472
2473
/*[clinic input]
2474
@critical_section
2475
@getter
2476
_asyncio.Task._must_cancel
2477
[clinic start generated code]*/
2478
2479
static PyObject *
2480
_asyncio_Task__must_cancel_get_impl(TaskObj *self)
2481
/*[clinic end generated code: output=70e79b900996c363 input=2d04529fb23feedf]*/
2482
0
{
2483
0
    if (self->task_must_cancel) {
2484
0
        Py_RETURN_TRUE;
2485
0
    }
2486
0
    else {
2487
0
        Py_RETURN_FALSE;
2488
0
    }
2489
0
}
2490
2491
/*[clinic input]
2492
@critical_section
2493
@getter
2494
_asyncio.Task._coro
2495
[clinic start generated code]*/
2496
2497
static PyObject *
2498
_asyncio_Task__coro_get_impl(TaskObj *self)
2499
/*[clinic end generated code: output=a2726012ab5fd531 input=323c31a272020624]*/
2500
0
{
2501
0
    if (self->task_coro) {
2502
0
        return Py_NewRef(self->task_coro);
2503
0
    }
2504
2505
0
    Py_RETURN_NONE;
2506
0
}
2507
2508
2509
/*[clinic input]
2510
@critical_section
2511
@getter
2512
_asyncio.Task._fut_waiter
2513
[clinic start generated code]*/
2514
2515
static PyObject *
2516
_asyncio_Task__fut_waiter_get_impl(TaskObj *self)
2517
/*[clinic end generated code: output=c4f966b847fefcdf input=4d1005d725e72db7]*/
2518
0
{
2519
0
    if (self->task_fut_waiter) {
2520
0
        return Py_NewRef(self->task_fut_waiter);
2521
0
    }
2522
2523
0
    Py_RETURN_NONE;
2524
0
}
2525
2526
static PyObject *
2527
TaskObj_repr(PyObject *task)
2528
0
{
2529
0
    asyncio_state *state = get_asyncio_state_by_def(task);
2530
0
    return PyObject_CallOneArg(state->asyncio_task_repr_func, task);
2531
0
}
2532
2533
2534
/*[clinic input]
2535
@critical_section
2536
_asyncio.Task._make_cancelled_error
2537
2538
Create the CancelledError to raise if the Task is cancelled.
2539
2540
This should only be called once when handling a cancellation since
2541
it erases the context exception value.
2542
[clinic start generated code]*/
2543
2544
static PyObject *
2545
_asyncio_Task__make_cancelled_error_impl(TaskObj *self)
2546
/*[clinic end generated code: output=55a819e8b4276fab input=2d3213be0cb02390]*/
2547
0
{
2548
0
    FutureObj *fut = (FutureObj*)self;
2549
0
    return _asyncio_Future__make_cancelled_error_impl(fut);
2550
0
}
2551
2552
2553
/*[clinic input]
2554
@critical_section
2555
_asyncio.Task.cancel
2556
2557
    msg: object = None
2558
2559
Request that this task cancel itself.
2560
2561
This arranges for a CancelledError to be thrown into the
2562
wrapped coroutine on the next cycle through the event loop.
2563
The coroutine then has a chance to clean up or even deny
2564
the request using try/except/finally.
2565
2566
Unlike Future.cancel, this does not guarantee that the
2567
task will be cancelled: the exception might be caught and
2568
acted upon, delaying cancellation of the task or preventing
2569
cancellation completely.  The task may also return a value or
2570
raise a different exception.
2571
2572
Immediately after this method is called, Task.cancelled() will
2573
not return True (unless the task was already cancelled).  A
2574
task will be marked as cancelled when the wrapped coroutine
2575
terminates with a CancelledError exception (even if cancel()
2576
was not called).
2577
2578
This also increases the task's count of cancellation requests.
2579
[clinic start generated code]*/
2580
2581
static PyObject *
2582
_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
2583
/*[clinic end generated code: output=c66b60d41c74f9f1 input=6125d45b9a6a5abd]*/
2584
0
{
2585
0
    self->task_log_tb = 0;
2586
2587
0
    if (self->task_state != STATE_PENDING) {
2588
0
        Py_RETURN_FALSE;
2589
0
    }
2590
2591
0
    self->task_num_cancels_requested += 1;
2592
2593
    // These three lines are controversial.  See discussion starting at
2594
    // https://github.com/python/cpython/pull/31394#issuecomment-1053545331
2595
    // and corresponding code in tasks.py.
2596
    // if (self->task_num_cancels_requested > 1) {
2597
    //     Py_RETURN_FALSE;
2598
    // }
2599
2600
0
    if (self->task_fut_waiter) {
2601
0
        PyObject *res;
2602
0
        int is_true;
2603
2604
0
        res = PyObject_CallMethodOneArg(self->task_fut_waiter,
2605
0
                                           &_Py_ID(cancel), msg);
2606
0
        if (res == NULL) {
2607
0
            return NULL;
2608
0
        }
2609
2610
0
        is_true = PyObject_IsTrue(res);
2611
0
        Py_DECREF(res);
2612
0
        if (is_true < 0) {
2613
0
            return NULL;
2614
0
        }
2615
2616
0
        if (is_true) {
2617
0
            Py_RETURN_TRUE;
2618
0
        }
2619
0
    }
2620
2621
0
    self->task_must_cancel = 1;
2622
0
    Py_XINCREF(msg);
2623
0
    Py_XSETREF(self->task_cancel_msg, msg);
2624
0
    Py_RETURN_TRUE;
2625
0
}
2626
2627
/*[clinic input]
2628
@critical_section
2629
_asyncio.Task.cancelling
2630
2631
Return the count of the task's cancellation requests.
2632
2633
This count is incremented when .cancel() is called
2634
and may be decremented using .uncancel().
2635
[clinic start generated code]*/
2636
2637
static PyObject *
2638
_asyncio_Task_cancelling_impl(TaskObj *self)
2639
/*[clinic end generated code: output=803b3af96f917d7e input=5ef89b1b38f080ee]*/
2640
/*[clinic end generated code]*/
2641
0
{
2642
0
    return PyLong_FromLong(self->task_num_cancels_requested);
2643
0
}
2644
2645
/*[clinic input]
2646
@critical_section
2647
_asyncio.Task.uncancel
2648
2649
Decrement the task's count of cancellation requests.
2650
2651
This should be used by tasks that catch CancelledError
2652
and wish to continue indefinitely until they are cancelled again.
2653
2654
Returns the remaining number of cancellation requests.
2655
[clinic start generated code]*/
2656
2657
static PyObject *
2658
_asyncio_Task_uncancel_impl(TaskObj *self)
2659
/*[clinic end generated code: output=58184d236a817d3c input=cb3220b0e5afd61d]*/
2660
/*[clinic end generated code]*/
2661
0
{
2662
0
    if (self->task_num_cancels_requested > 0) {
2663
0
        self->task_num_cancels_requested -= 1;
2664
0
        if (self->task_num_cancels_requested == 0) {
2665
0
            self->task_must_cancel = 0;
2666
0
        }
2667
0
    }
2668
0
    return PyLong_FromLong(self->task_num_cancels_requested);
2669
0
}
2670
2671
/*[clinic input]
2672
_asyncio.Task.get_stack
2673
2674
    cls: defining_class
2675
    /
2676
    *
2677
    limit: object = None
2678
2679
Return the list of stack frames for this task's coroutine.
2680
2681
If the coroutine is not done, this returns the stack where it is
2682
suspended.  If the coroutine has completed successfully or was
2683
cancelled, this returns an empty list.  If the coroutine was
2684
terminated by an exception, this returns the list of traceback
2685
frames.
2686
2687
The frames are always ordered from oldest to newest.
2688
2689
The optional limit gives the maximum number of frames to
2690
return; by default all available frames are returned.  Its
2691
meaning differs depending on whether a stack or a traceback is
2692
returned: the newest frames of a stack are returned, but the
2693
oldest frames of a traceback are returned.  (This matches the
2694
behavior of the traceback module.)
2695
2696
For reasons beyond our control, only one stack frame is
2697
returned for a suspended coroutine.
2698
[clinic start generated code]*/
2699
2700
static PyObject *
2701
_asyncio_Task_get_stack_impl(TaskObj *self, PyTypeObject *cls,
2702
                             PyObject *limit)
2703
/*[clinic end generated code: output=6774dfc10d3857fa input=8e01c9b2618ae953]*/
2704
0
{
2705
0
    asyncio_state *state = get_asyncio_state_by_cls(cls);
2706
0
    PyObject *stack[] = {(PyObject *)self, limit};
2707
0
    return PyObject_Vectorcall(state->asyncio_task_get_stack_func,
2708
0
                               stack, 2, NULL);
2709
0
}
2710
2711
/*[clinic input]
2712
_asyncio.Task.print_stack
2713
2714
    cls: defining_class
2715
    /
2716
    *
2717
    limit: object = None
2718
    file: object = None
2719
2720
Print the stack or traceback for this task's coroutine.
2721
2722
This produces output similar to that of the traceback module,
2723
for the frames retrieved by get_stack().  The limit argument
2724
is passed to get_stack().  The file argument is an I/O stream
2725
to which the output is written; by default output is written
2726
to sys.stderr.
2727
[clinic start generated code]*/
2728
2729
static PyObject *
2730
_asyncio_Task_print_stack_impl(TaskObj *self, PyTypeObject *cls,
2731
                               PyObject *limit, PyObject *file)
2732
/*[clinic end generated code: output=b38affe9289ec826 input=150b35ba2d3a7dee]*/
2733
0
{
2734
0
    asyncio_state *state = get_asyncio_state_by_cls(cls);
2735
0
    PyObject *stack[] = {(PyObject *)self, limit, file};
2736
0
    return PyObject_Vectorcall(state->asyncio_task_print_stack_func,
2737
0
                               stack, 3, NULL);
2738
0
}
2739
2740
/*[clinic input]
2741
_asyncio.Task.set_result
2742
2743
    result: object
2744
    /
2745
[clinic start generated code]*/
2746
2747
static PyObject *
2748
_asyncio_Task_set_result_impl(TaskObj *self, PyObject *result)
2749
/*[clinic end generated code: output=e9d8e3cdaf18e258 input=9d1a00c07be41bab]*/
2750
0
{
2751
0
    PyErr_SetString(PyExc_RuntimeError,
2752
0
                    "Task does not support set_result operation");
2753
0
    return NULL;
2754
0
}
2755
2756
/*[clinic input]
2757
_asyncio.Task.set_exception
2758
2759
    exception: object
2760
    /
2761
[clinic start generated code]*/
2762
2763
static PyObject *
2764
_asyncio_Task_set_exception_impl(TaskObj *self, PyObject *exception)
2765
/*[clinic end generated code: output=96a91790c192cc7d input=9a8f65c83dcf893a]*/
2766
0
{
2767
0
    PyErr_SetString(PyExc_RuntimeError,
2768
0
                    "Task does not support set_exception operation");
2769
0
    return NULL;
2770
0
}
2771
2772
/*[clinic input]
2773
@critical_section
2774
_asyncio.Task.get_coro
2775
[clinic start generated code]*/
2776
2777
static PyObject *
2778
_asyncio_Task_get_coro_impl(TaskObj *self)
2779
/*[clinic end generated code: output=bcac27c8cc6c8073 input=a47f81427e39fe0c]*/
2780
0
{
2781
0
    if (self->task_coro) {
2782
0
        return Py_NewRef(self->task_coro);
2783
0
    }
2784
2785
0
    Py_RETURN_NONE;
2786
0
}
2787
2788
/*[clinic input]
2789
_asyncio.Task.get_context
2790
[clinic start generated code]*/
2791
2792
static PyObject *
2793
_asyncio_Task_get_context_impl(TaskObj *self)
2794
/*[clinic end generated code: output=6996f53d3dc01aef input=87c0b209b8fceeeb]*/
2795
0
{
2796
0
    return Py_NewRef(self->task_context);
2797
0
}
2798
2799
/*[clinic input]
2800
@critical_section
2801
_asyncio.Task.get_name
2802
[clinic start generated code]*/
2803
2804
static PyObject *
2805
_asyncio_Task_get_name_impl(TaskObj *self)
2806
/*[clinic end generated code: output=0ecf1570c3b37a8f input=92a8f30c85034249]*/
2807
0
{
2808
0
    if (self->task_name) {
2809
0
        if (PyLong_CheckExact(self->task_name)) {
2810
0
            PyObject *name = PyUnicode_FromFormat("Task-%S", self->task_name);
2811
0
            if (name == NULL) {
2812
0
                return NULL;
2813
0
            }
2814
0
            Py_SETREF(self->task_name, name);
2815
0
        }
2816
0
        return Py_NewRef(self->task_name);
2817
0
    }
2818
2819
0
    Py_RETURN_NONE;
2820
0
}
2821
2822
/*[clinic input]
2823
@critical_section
2824
_asyncio.Task.set_name
2825
2826
    value: object
2827
    /
2828
[clinic start generated code]*/
2829
2830
static PyObject *
2831
_asyncio_Task_set_name_impl(TaskObj *self, PyObject *value)
2832
/*[clinic end generated code: output=f88ff4c0d64a9a6f input=e8d400ad64bad799]*/
2833
0
{
2834
0
    if (!PyUnicode_CheckExact(value)) {
2835
0
        value = PyObject_Str(value);
2836
0
        if (value == NULL) {
2837
0
            return NULL;
2838
0
        }
2839
0
    } else {
2840
0
        Py_INCREF(value);
2841
0
    }
2842
2843
0
    Py_XSETREF(self->task_name, value);
2844
0
    Py_RETURN_NONE;
2845
0
}
2846
2847
static void
2848
TaskObj_finalize(PyObject *op)
2849
0
{
2850
0
    TaskObj *task = (TaskObj*)op;
2851
0
    PyObject *context;
2852
0
    PyObject *message = NULL;
2853
0
    PyObject *func;
2854
2855
0
    if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2856
0
        goto done;
2857
0
    }
2858
2859
    /* Save the current exception, if any. */
2860
0
    PyObject *exc = PyErr_GetRaisedException();
2861
2862
0
    context = PyDict_New();
2863
0
    if (context == NULL) {
2864
0
        goto finally;
2865
0
    }
2866
2867
0
    message = PyUnicode_FromString("Task was destroyed but it is pending!");
2868
0
    if (message == NULL) {
2869
0
        goto finally;
2870
0
    }
2871
2872
0
    if (PyDict_SetItem(context, &_Py_ID(message), message) < 0 ||
2873
0
        PyDict_SetItem(context, &_Py_ID(task), (PyObject*)task) < 0)
2874
0
    {
2875
0
        goto finally;
2876
0
    }
2877
2878
0
    if (task->task_source_tb != NULL) {
2879
0
        if (PyDict_SetItem(context, &_Py_ID(source_traceback),
2880
0
                              task->task_source_tb) < 0)
2881
0
        {
2882
0
            goto finally;
2883
0
        }
2884
0
    }
2885
2886
0
    func = PyObject_GetAttr(task->task_loop, &_Py_ID(call_exception_handler));
2887
0
    if (func != NULL) {
2888
0
        PyObject *res = PyObject_CallOneArg(func, context);
2889
0
        if (res == NULL) {
2890
0
            PyErr_FormatUnraisable("Exception ignored while calling asyncio "
2891
0
                                   "function %R", func);
2892
0
        }
2893
0
        else {
2894
0
            Py_DECREF(res);
2895
0
        }
2896
0
        Py_DECREF(func);
2897
0
    }
2898
2899
0
finally:
2900
0
    Py_XDECREF(context);
2901
0
    Py_XDECREF(message);
2902
2903
    /* Restore the saved exception. */
2904
0
    PyErr_SetRaisedException(exc);
2905
2906
0
done:
2907
0
    FutureObj_finalize((PyObject*)task);
2908
0
}
2909
2910
static void TaskObj_dealloc(PyObject *);  /* Needs Task_CheckExact */
2911
2912
static PyMethodDef TaskType_methods[] = {
2913
    _ASYNCIO_FUTURE_RESULT_METHODDEF
2914
    _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
2915
    _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2916
    _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2917
    _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2918
    _ASYNCIO_FUTURE_DONE_METHODDEF
2919
    _ASYNCIO_TASK_SET_RESULT_METHODDEF
2920
    _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
2921
    _ASYNCIO_TASK_CANCEL_METHODDEF
2922
    _ASYNCIO_TASK_CANCELLING_METHODDEF
2923
    _ASYNCIO_TASK_UNCANCEL_METHODDEF
2924
    _ASYNCIO_TASK_GET_STACK_METHODDEF
2925
    _ASYNCIO_TASK_PRINT_STACK_METHODDEF
2926
    _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
2927
    _ASYNCIO_TASK_GET_NAME_METHODDEF
2928
    _ASYNCIO_TASK_SET_NAME_METHODDEF
2929
    _ASYNCIO_TASK_GET_CORO_METHODDEF
2930
    _ASYNCIO_TASK_GET_CONTEXT_METHODDEF
2931
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS,
2932
    PyDoc_STR("Tasks are generic over the return type of their wrapped coroutines")},
2933
    {NULL, NULL}        /* Sentinel */
2934
};
2935
2936
static PyGetSetDef TaskType_getsetlist[] = {
2937
    _ASYNCIO_TASK__LOG_DESTROY_PENDING_GETSETDEF
2938
    _ASYNCIO_TASK__MUST_CANCEL_GETSETDEF
2939
    _ASYNCIO_TASK__CORO_GETSETDEF
2940
    _ASYNCIO_TASK__FUT_WAITER_GETSETDEF
2941
    {NULL} /* Sentinel */
2942
};
2943
2944
static PyType_Slot Task_slots[] = {
2945
    {Py_tp_dealloc, TaskObj_dealloc},
2946
    {Py_tp_repr, TaskObj_repr},
2947
    {Py_tp_doc, (void *)_asyncio_Task___init____doc__},
2948
    {Py_tp_traverse, TaskObj_traverse},
2949
    {Py_tp_clear, TaskObj_clear},
2950
    {Py_tp_iter, future_new_iter},
2951
    {Py_tp_methods, TaskType_methods},
2952
    {Py_tp_getset, TaskType_getsetlist},
2953
    {Py_tp_init, _asyncio_Task___init__},
2954
    {Py_tp_new, PyType_GenericNew},
2955
    {Py_tp_finalize, TaskObj_finalize},
2956
2957
    // async slots
2958
    {Py_am_await, future_new_iter},
2959
    {0, NULL},
2960
};
2961
2962
static PyType_Spec Task_spec = {
2963
    .name = "_asyncio.Task",
2964
    .basicsize = sizeof(TaskObj),
2965
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
2966
              Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT |
2967
              Py_TPFLAGS_MANAGED_WEAKREF),
2968
    .slots = Task_slots,
2969
};
2970
2971
static void
2972
TaskObj_dealloc(PyObject *self)
2973
0
{
2974
0
    if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2975
0
        return; // resurrected
2976
0
    }
2977
    // unregister the task after finalization so that
2978
    // if the task gets resurrected, it remains registered
2979
0
    unregister_task((TaskObj *)self);
2980
2981
0
    PyTypeObject *tp = Py_TYPE(self);
2982
0
    PyObject_GC_UnTrack(self);
2983
2984
0
    PyObject_ClearWeakRefs(self);
2985
2986
0
    (void)TaskObj_clear(self);
2987
0
    tp->tp_free(self);
2988
0
    Py_DECREF(tp);
2989
0
}
2990
2991
static int
2992
task_call_step_soon(asyncio_state *state, TaskObj *task, PyObject *arg)
2993
0
{
2994
0
    PyObject *cb = TaskStepMethWrapper_new(task, arg);
2995
0
    if (cb == NULL) {
2996
0
        return -1;
2997
0
    }
2998
2999
0
    int ret = call_soon(state, task->task_loop, cb, NULL, task->task_context);
3000
0
    Py_DECREF(cb);
3001
0
    return ret;
3002
0
}
3003
3004
static PyObject *
3005
task_set_error_soon(asyncio_state *state, TaskObj *task, PyObject *et,
3006
                    const char *format, ...)
3007
0
{
3008
0
    PyObject* msg;
3009
3010
0
    va_list vargs;
3011
0
    va_start(vargs, format);
3012
0
    msg = PyUnicode_FromFormatV(format, vargs);
3013
0
    va_end(vargs);
3014
3015
0
    if (msg == NULL) {
3016
0
        return NULL;
3017
0
    }
3018
3019
0
    PyObject *e = PyObject_CallOneArg(et, msg);
3020
0
    Py_DECREF(msg);
3021
0
    if (e == NULL) {
3022
0
        return NULL;
3023
0
    }
3024
3025
0
    if (task_call_step_soon(state, task, e) == -1) {
3026
0
        Py_DECREF(e);
3027
0
        return NULL;
3028
0
    }
3029
3030
0
    Py_DECREF(e);
3031
0
    Py_RETURN_NONE;
3032
0
}
3033
3034
static inline int
3035
gen_status_from_result(PyObject **result)
3036
0
{
3037
0
    if (*result != NULL) {
3038
0
        return PYGEN_NEXT;
3039
0
    }
3040
0
    if (_PyGen_FetchStopIterationValue(result) == 0) {
3041
0
        return PYGEN_RETURN;
3042
0
    }
3043
3044
0
    assert(PyErr_Occurred());
3045
0
    return PYGEN_ERROR;
3046
0
}
3047
3048
static PyObject *
3049
task_step_impl(asyncio_state *state, TaskObj *task, PyObject *exc)
3050
0
{
3051
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(task);
3052
3053
0
    int clear_exc = 0;
3054
0
    PyObject *result = NULL;
3055
0
    PyObject *coro;
3056
0
    PyObject *o;
3057
3058
0
    if (task->task_state != STATE_PENDING) {
3059
0
        PyErr_Format(state->asyncio_InvalidStateError,
3060
0
                     "__step(): already done: %R %R",
3061
0
                     task,
3062
0
                     exc ? exc : Py_None);
3063
0
        goto fail;
3064
0
    }
3065
3066
0
    if (task->task_must_cancel) {
3067
0
        assert(exc != Py_None);
3068
3069
0
        if (!exc || !PyErr_GivenExceptionMatches(exc, state->asyncio_CancelledError)) {
3070
            /* exc was not a CancelledError */
3071
0
            exc = create_cancelled_error(state, (FutureObj*)task);
3072
3073
0
            if (!exc) {
3074
0
                goto fail;
3075
0
            }
3076
0
            clear_exc = 1;
3077
0
        }
3078
3079
0
        task->task_must_cancel = 0;
3080
0
    }
3081
3082
0
    Py_CLEAR(task->task_fut_waiter);
3083
3084
0
    coro = task->task_coro;
3085
0
    if (coro == NULL) {
3086
0
        PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
3087
0
        if (clear_exc) {
3088
            /* We created 'exc' during this call */
3089
0
            Py_DECREF(exc);
3090
0
        }
3091
0
        return NULL;
3092
0
    }
3093
3094
0
    int gen_status = PYGEN_ERROR;
3095
0
    if (exc == NULL) {
3096
0
        gen_status = PyIter_Send(coro, Py_None, &result);
3097
0
    }
3098
0
    else {
3099
0
        result = PyObject_CallMethodOneArg(coro, &_Py_ID(throw), exc);
3100
0
        gen_status = gen_status_from_result(&result);
3101
0
        if (clear_exc) {
3102
            /* We created 'exc' during this call */
3103
0
            Py_DECREF(exc);
3104
0
        }
3105
0
    }
3106
3107
0
    if (gen_status == PYGEN_RETURN || gen_status == PYGEN_ERROR) {
3108
0
        if (result != NULL) {
3109
            /* The error is StopIteration and that means that
3110
               the underlying coroutine has resolved */
3111
3112
0
            PyObject *tmp;
3113
0
            if (task->task_must_cancel) {
3114
                // Task is cancelled right before coro stops.
3115
0
                task->task_must_cancel = 0;
3116
0
                tmp = future_cancel(state, (FutureObj*)task,
3117
0
                                    task->task_cancel_msg);
3118
0
            }
3119
0
            else {
3120
0
                tmp = future_set_result(state, (FutureObj*)task, result);
3121
0
            }
3122
3123
0
            Py_DECREF(result);
3124
3125
0
            if (tmp == NULL) {
3126
0
                return NULL;
3127
0
            }
3128
0
            Py_DECREF(tmp);
3129
0
            Py_RETURN_NONE;
3130
0
        }
3131
3132
0
        if (PyErr_ExceptionMatches(state->asyncio_CancelledError)) {
3133
            /* CancelledError */
3134
3135
0
            PyObject *exc = PyErr_GetRaisedException();
3136
0
            assert(exc);
3137
3138
0
            FutureObj *fut = (FutureObj*)task;
3139
            /* transfer ownership */
3140
0
            fut->fut_cancelled_exc = exc;
3141
3142
0
            return future_cancel(state, fut, NULL);
3143
0
        }
3144
3145
        /* Some other exception; pop it and call Task.set_exception() */
3146
0
        PyObject *exc = PyErr_GetRaisedException();
3147
0
        assert(exc);
3148
3149
0
        o = future_set_exception(state, (FutureObj*)task, exc);
3150
0
        if (!o) {
3151
            /* An exception in Task.set_exception() */
3152
0
            Py_DECREF(exc);
3153
0
            goto fail;
3154
0
        }
3155
0
        assert(o == Py_None);
3156
0
        Py_DECREF(o);
3157
3158
0
        if (PyErr_GivenExceptionMatches(exc, PyExc_KeyboardInterrupt) ||
3159
0
            PyErr_GivenExceptionMatches(exc, PyExc_SystemExit))
3160
0
        {
3161
            /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
3162
0
            PyErr_SetRaisedException(exc);
3163
0
            goto fail;
3164
0
        }
3165
3166
0
        Py_DECREF(exc);
3167
3168
0
        Py_RETURN_NONE;
3169
0
    }
3170
3171
0
    PyObject *ret = task_step_handle_result_impl(state, task, result);
3172
0
    return ret;
3173
3174
0
fail:
3175
0
    return NULL;
3176
0
}
3177
3178
3179
static PyObject *
3180
task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *result)
3181
0
{
3182
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(task);
3183
3184
0
    int res;
3185
0
    PyObject *o;
3186
3187
0
    if (result == (PyObject*)task) {
3188
        /* We have a task that wants to await on itself */
3189
0
        goto self_await;
3190
0
    }
3191
3192
    /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
3193
0
    if (Future_CheckExact(state, result) || Task_CheckExact(state, result)) {
3194
0
        PyObject *wrapper;
3195
0
        PyObject *tmp;
3196
0
        FutureObj *fut = (FutureObj*)result;
3197
3198
        /* Check if `result` future is attached to a different loop */
3199
0
        if (fut->fut_loop != task->task_loop) {
3200
0
            goto different_loop;
3201
0
        }
3202
3203
0
        if (!fut->fut_blocking) {
3204
0
            goto yield_insteadof_yf;
3205
0
        }
3206
0
        int res;
3207
0
        Py_BEGIN_CRITICAL_SECTION(result);
3208
0
        res = future_awaited_by_add(state, (FutureObj *)result, (PyObject *)task);
3209
0
        Py_END_CRITICAL_SECTION();
3210
0
        if (res) {
3211
0
            goto fail;
3212
0
        }
3213
3214
0
        fut->fut_blocking = 0;
3215
3216
        /* result.add_done_callback(task._wakeup) */
3217
0
        wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
3218
0
        if (wrapper == NULL) {
3219
0
            goto fail;
3220
0
        }
3221
0
        Py_BEGIN_CRITICAL_SECTION(result);
3222
0
        tmp = future_add_done_callback(state,
3223
0
            (FutureObj*)result, wrapper, task->task_context);
3224
0
        Py_END_CRITICAL_SECTION();
3225
0
        Py_DECREF(wrapper);
3226
0
        if (tmp == NULL) {
3227
0
            goto fail;
3228
0
        }
3229
0
        Py_DECREF(tmp);
3230
3231
        /* task._fut_waiter = result */
3232
0
        task->task_fut_waiter = result;  /* no incref is necessary */
3233
3234
0
        if (task->task_must_cancel) {
3235
0
            PyObject *r;
3236
0
            int is_true;
3237
3238
            // Beware: An evil `__getattribute__` could
3239
            // prematurely delete task->task_cancel_msg before the
3240
            // task is cancelled, thereby causing a UAF crash.
3241
            //
3242
            // See https://github.com/python/cpython/issues/126138
3243
0
            PyObject *task_cancel_msg = Py_NewRef(task->task_cancel_msg);
3244
0
            r = PyObject_CallMethodOneArg(result, &_Py_ID(cancel),
3245
0
                                          task_cancel_msg);
3246
0
            Py_DECREF(task_cancel_msg);
3247
3248
0
            if (r == NULL) {
3249
0
                return NULL;
3250
0
            }
3251
0
            is_true = PyObject_IsTrue(r);
3252
0
            Py_DECREF(r);
3253
0
            if (is_true < 0) {
3254
0
                return NULL;
3255
0
            }
3256
0
            else if (is_true) {
3257
0
                task->task_must_cancel = 0;
3258
0
            }
3259
0
        }
3260
3261
0
        Py_RETURN_NONE;
3262
0
    }
3263
3264
    /* Check if `result` is None */
3265
0
    if (result == Py_None) {
3266
        /* Bare yield relinquishes control for one event loop iteration. */
3267
0
        if (task_call_step_soon(state, task, NULL)) {
3268
0
            goto fail;
3269
0
        }
3270
0
        return result;
3271
0
    }
3272
3273
    /* Check if `result` is a Future-compatible object */
3274
0
    if (PyObject_GetOptionalAttr(result, &_Py_ID(_asyncio_future_blocking), &o) < 0) {
3275
0
        goto fail;
3276
0
    }
3277
0
    if (o != NULL && o != Py_None) {
3278
        /* `result` is a Future-compatible object */
3279
0
        PyObject *wrapper;
3280
0
        PyObject *tmp;
3281
3282
0
        int blocking = PyObject_IsTrue(o);
3283
0
        Py_DECREF(o);
3284
0
        if (blocking < 0) {
3285
0
            goto fail;
3286
0
        }
3287
3288
        /* Check if `result` future is attached to a different loop */
3289
0
        PyObject *oloop = get_future_loop(state, result);
3290
0
        if (oloop == NULL) {
3291
0
            goto fail;
3292
0
        }
3293
0
        if (oloop != task->task_loop) {
3294
0
            Py_DECREF(oloop);
3295
0
            goto different_loop;
3296
0
        }
3297
0
        Py_DECREF(oloop);
3298
3299
0
        if (!blocking) {
3300
0
            goto yield_insteadof_yf;
3301
0
        }
3302
3303
0
        if (TaskOrFuture_Check(state, result)) {
3304
0
            int res;
3305
0
            Py_BEGIN_CRITICAL_SECTION(result);
3306
0
            res = future_awaited_by_add(state, (FutureObj *)result, (PyObject *)task);
3307
0
            Py_END_CRITICAL_SECTION();
3308
0
            if (res) {
3309
0
                goto fail;
3310
0
            }
3311
0
        }
3312
3313
        /* result._asyncio_future_blocking = False */
3314
0
        if (PyObject_SetAttr(
3315
0
                result, &_Py_ID(_asyncio_future_blocking), Py_False) == -1) {
3316
0
            goto fail;
3317
0
        }
3318
3319
0
        wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
3320
0
        if (wrapper == NULL) {
3321
0
            goto fail;
3322
0
        }
3323
3324
        /* result.add_done_callback(task._wakeup) */
3325
0
        PyObject *add_cb = PyObject_GetAttr(
3326
0
            result, &_Py_ID(add_done_callback));
3327
0
        if (add_cb == NULL) {
3328
0
            Py_DECREF(wrapper);
3329
0
            goto fail;
3330
0
        }
3331
0
        PyObject *stack[2];
3332
0
        stack[0] = wrapper;
3333
0
        stack[1] = (PyObject *)task->task_context;
3334
0
        EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, add_cb);
3335
0
        tmp = PyObject_Vectorcall(add_cb, stack, 1, state->context_kwname);
3336
0
        Py_DECREF(add_cb);
3337
0
        Py_DECREF(wrapper);
3338
0
        if (tmp == NULL) {
3339
0
            goto fail;
3340
0
        }
3341
0
        Py_DECREF(tmp);
3342
3343
        /* task._fut_waiter = result */
3344
0
        task->task_fut_waiter = result;  /* no incref is necessary */
3345
3346
0
        if (task->task_must_cancel) {
3347
0
            PyObject *r;
3348
0
            int is_true;
3349
3350
            // Beware: An evil `__getattribute__` could
3351
            // prematurely delete task->task_cancel_msg before the
3352
            // task is cancelled, thereby causing a UAF crash.
3353
            //
3354
            // See https://github.com/python/cpython/issues/126138
3355
0
            PyObject *task_cancel_msg = Py_NewRef(task->task_cancel_msg);
3356
0
            r = PyObject_CallMethodOneArg(result, &_Py_ID(cancel),
3357
0
                                          task_cancel_msg);
3358
0
            Py_DECREF(task_cancel_msg);
3359
3360
0
            if (r == NULL) {
3361
0
                return NULL;
3362
0
            }
3363
0
            is_true = PyObject_IsTrue(r);
3364
0
            Py_DECREF(r);
3365
0
            if (is_true < 0) {
3366
0
                return NULL;
3367
0
            }
3368
0
            else if (is_true) {
3369
0
                task->task_must_cancel = 0;
3370
0
            }
3371
0
        }
3372
3373
0
        Py_RETURN_NONE;
3374
0
    }
3375
3376
0
    Py_XDECREF(o);
3377
    /* Check if `result` is a generator */
3378
0
    res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
3379
0
    if (res < 0) {
3380
0
        goto fail;
3381
0
    }
3382
0
    if (res) {
3383
        /* `result` is a generator */
3384
0
        o = task_set_error_soon(
3385
0
            state, task, PyExc_RuntimeError,
3386
0
            "yield was used instead of yield from for "
3387
0
            "generator in task %R with %R", task, result);
3388
0
        Py_DECREF(result);
3389
0
        return o;
3390
0
    }
3391
3392
    /* The `result` is none of the above */
3393
0
    o = task_set_error_soon(
3394
0
        state, task, PyExc_RuntimeError, "Task got bad yield: %R", result);
3395
0
    Py_DECREF(result);
3396
0
    return o;
3397
3398
0
self_await:
3399
0
    o = task_set_error_soon(
3400
0
        state, task, PyExc_RuntimeError,
3401
0
        "Task cannot await on itself: %R", task);
3402
0
    Py_DECREF(result);
3403
0
    return o;
3404
3405
0
yield_insteadof_yf:
3406
0
    o = task_set_error_soon(
3407
0
        state, task, PyExc_RuntimeError,
3408
0
        "yield was used instead of yield from "
3409
0
        "in task %R with %R",
3410
0
        task, result);
3411
0
    Py_DECREF(result);
3412
0
    return o;
3413
3414
0
different_loop:
3415
0
    o = task_set_error_soon(
3416
0
        state, task, PyExc_RuntimeError,
3417
0
        "Task %R got Future %R attached to a different loop",
3418
0
        task, result);
3419
0
    Py_DECREF(result);
3420
0
    return o;
3421
3422
0
fail:
3423
0
    Py_XDECREF(result);
3424
0
    return NULL;
3425
0
}
3426
3427
static PyObject *
3428
task_step(asyncio_state *state, TaskObj *task, PyObject *exc)
3429
0
{
3430
0
    PyObject *res;
3431
3432
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3433
3434
0
    if (enter_task(ts, task->task_loop, (PyObject*)task) < 0) {
3435
0
        return NULL;
3436
0
    }
3437
3438
0
    res = task_step_impl(state, task, exc);
3439
3440
0
    if (res == NULL) {
3441
0
        PyObject *exc = PyErr_GetRaisedException();
3442
0
        leave_task(ts, task->task_loop, (PyObject*)task);
3443
0
        _PyErr_ChainExceptions1(exc);
3444
0
        return NULL;
3445
0
    }
3446
0
    else {
3447
0
        if (leave_task(ts, task->task_loop, (PyObject*)task) < 0) {
3448
0
            Py_DECREF(res);
3449
0
            return NULL;
3450
0
        }
3451
0
        else {
3452
0
            return res;
3453
0
        }
3454
0
    }
3455
0
}
3456
3457
static int
3458
task_eager_start(_PyThreadStateImpl *ts, asyncio_state *state, TaskObj *task)
3459
0
{
3460
0
    assert(task != NULL);
3461
0
    PyObject *prevtask = swap_current_task(ts, task->task_loop, (PyObject *)task);
3462
0
    if (prevtask == NULL) {
3463
0
        return -1;
3464
0
    }
3465
    // register the task into the linked list of tasks
3466
    // if the task completes eagerly (without suspending) then it will unregister itself
3467
    // in future_schedule_callbacks when done, otherwise
3468
    // it will continue as a regular (non-eager) asyncio task
3469
0
    register_task(ts, task);
3470
3471
0
    if (_PyContext_Enter(&ts->base, task->task_context) == -1) {
3472
0
        Py_DECREF(prevtask);
3473
0
        return -1;
3474
0
    }
3475
3476
0
    int retval = 0;
3477
3478
0
    PyObject *stepres;
3479
0
    Py_BEGIN_CRITICAL_SECTION(task);
3480
0
    stepres = task_step_impl(state, task, NULL);
3481
0
    Py_END_CRITICAL_SECTION();
3482
0
    if (stepres == NULL) {
3483
0
        PyObject *exc = PyErr_GetRaisedException();
3484
0
        _PyErr_ChainExceptions1(exc);
3485
0
        retval = -1;
3486
0
    } else {
3487
0
        Py_DECREF(stepres);
3488
0
    }
3489
3490
0
    PyObject *curtask = swap_current_task(ts, task->task_loop, prevtask);
3491
0
    Py_DECREF(prevtask);
3492
0
    if (curtask == NULL) {
3493
0
        retval = -1;
3494
0
    } else {
3495
0
        assert(curtask == (PyObject *)task);
3496
0
        Py_DECREF(curtask);
3497
0
    }
3498
3499
0
    if (_PyContext_Exit(&ts->base, task->task_context) == -1) {
3500
0
        retval = -1;
3501
0
    }
3502
3503
0
    if (task->task_state != STATE_PENDING) {
3504
        // This seems to really help performance on pyperformance benchmarks
3505
0
        clear_task_coro(task);
3506
0
    }
3507
3508
0
    return retval;
3509
0
}
3510
3511
static PyObject *
3512
task_wakeup_lock_held(TaskObj *task, PyObject *o)
3513
0
{
3514
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(task);
3515
3516
0
    PyObject *result;
3517
0
    assert(o);
3518
3519
0
    asyncio_state *state = get_asyncio_state_by_def((PyObject *)task);
3520
3521
0
    if (TaskOrFuture_Check(state, o)) {
3522
0
        int res;
3523
0
        Py_BEGIN_CRITICAL_SECTION(o);
3524
0
        res = future_awaited_by_discard(state, (FutureObj *)o, (PyObject *)task);
3525
0
        Py_END_CRITICAL_SECTION();
3526
0
        if (res) {
3527
0
            return NULL;
3528
0
        }
3529
0
    }
3530
3531
0
    if (Future_CheckExact(state, o) || Task_CheckExact(state, o)) {
3532
0
        PyObject *fut_result = NULL;
3533
0
        int res;
3534
0
        Py_BEGIN_CRITICAL_SECTION(o);
3535
0
        res = future_get_result(state, (FutureObj*)o, &fut_result);
3536
0
        Py_END_CRITICAL_SECTION();
3537
0
        switch(res) {
3538
0
        case -1:
3539
0
            assert(fut_result == NULL);
3540
0
            break; /* exception raised */
3541
0
        case 0:
3542
0
            Py_DECREF(fut_result);
3543
0
            return task_step(state, task, NULL);
3544
0
        default:
3545
0
            assert(res == 1);
3546
0
            result = task_step(state, task, fut_result);
3547
0
            Py_DECREF(fut_result);
3548
0
            return result;
3549
0
        }
3550
0
    }
3551
0
    else {
3552
0
        PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
3553
0
        if (fut_result != NULL) {
3554
0
            Py_DECREF(fut_result);
3555
0
            return task_step(state, task, NULL);
3556
0
        }
3557
        /* exception raised */
3558
0
    }
3559
3560
0
    PyObject *exc = PyErr_GetRaisedException();
3561
0
    assert(exc);
3562
3563
0
    result = task_step(state, task, exc);
3564
3565
0
    Py_DECREF(exc);
3566
3567
0
    return result;
3568
0
}
3569
3570
static PyObject *
3571
task_wakeup(PyObject *op, PyObject *arg)
3572
0
{
3573
0
    TaskObj *task = (TaskObj*)op;
3574
0
    PyObject *res;
3575
0
    Py_BEGIN_CRITICAL_SECTION(task);
3576
0
    res = task_wakeup_lock_held(task, arg);
3577
0
    Py_END_CRITICAL_SECTION();
3578
0
    return res;
3579
0
}
3580
3581
3582
/*********************** Functions **************************/
3583
3584
3585
/*[clinic input]
3586
_asyncio._get_running_loop
3587
3588
Return the running event loop or None.
3589
3590
This is a low-level function intended to be used by event loops.
3591
This function is thread-specific.
3592
3593
[clinic start generated code]*/
3594
3595
static PyObject *
3596
_asyncio__get_running_loop_impl(PyObject *module)
3597
/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3598
0
{
3599
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3600
0
    PyObject *loop = Py_XNewRef(ts->asyncio_running_loop);
3601
0
    if (loop == NULL) {
3602
        /* There's no currently running event loop */
3603
0
        Py_RETURN_NONE;
3604
0
    }
3605
0
    return loop;
3606
0
}
3607
3608
/*[clinic input]
3609
_asyncio._set_running_loop
3610
    loop: 'O'
3611
    /
3612
3613
Set the running event loop.
3614
3615
This is a low-level function intended to be used by event loops.
3616
This function is thread-specific.
3617
[clinic start generated code]*/
3618
3619
static PyObject *
3620
_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3621
/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3622
0
{
3623
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3624
0
    if (loop == Py_None) {
3625
0
        loop = NULL;
3626
0
    }
3627
0
    Py_XSETREF(ts->asyncio_running_loop, Py_XNewRef(loop));
3628
0
    Py_RETURN_NONE;
3629
0
}
3630
3631
/*[clinic input]
3632
_asyncio.get_event_loop
3633
3634
Return an asyncio event loop.
3635
3636
When called from a coroutine or a callback (e.g. scheduled with
3637
call_soon or similar API), this function will always return the
3638
running event loop.
3639
3640
If there is no running event loop set, the function will return
3641
the result of `get_event_loop_policy().get_event_loop()` call.
3642
[clinic start generated code]*/
3643
3644
static PyObject *
3645
_asyncio_get_event_loop_impl(PyObject *module)
3646
/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3647
0
{
3648
0
    asyncio_state *state = get_asyncio_state(module);
3649
0
    return get_event_loop(state);
3650
0
}
3651
3652
/*[clinic input]
3653
_asyncio.get_running_loop
3654
3655
Return the running event loop.  Raise a RuntimeError if there is none.
3656
3657
This function is thread-specific.
3658
[clinic start generated code]*/
3659
3660
static PyObject *
3661
_asyncio_get_running_loop_impl(PyObject *module)
3662
/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3663
0
{
3664
0
    PyObject *loop;
3665
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3666
0
    loop = Py_XNewRef(ts->asyncio_running_loop);
3667
0
    if (loop == NULL) {
3668
        /* There's no currently running event loop */
3669
0
        PyErr_SetString(
3670
0
            PyExc_RuntimeError, "no running event loop");
3671
0
        return NULL;
3672
0
    }
3673
0
    return loop;
3674
0
}
3675
3676
/*[clinic input]
3677
_asyncio._register_task
3678
3679
    task: object
3680
3681
Register a new task in asyncio as executed by loop.
3682
3683
Returns None.
3684
[clinic start generated code]*/
3685
3686
static PyObject *
3687
_asyncio__register_task_impl(PyObject *module, PyObject *task)
3688
/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
3689
0
{
3690
0
    asyncio_state *state = get_asyncio_state(module);
3691
0
    if (Task_Check(state, task)) {
3692
        // task is an asyncio.Task instance or subclass, use efficient
3693
        // linked-list implementation.
3694
0
        _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3695
0
        register_task(ts, (TaskObj *)task);
3696
0
        Py_RETURN_NONE;
3697
0
    }
3698
    // As task does not inherit from asyncio.Task, fallback to less efficient
3699
    // weakset implementation.
3700
0
    PyObject *res = PyObject_CallMethodOneArg(state->non_asyncio_tasks,
3701
0
                                              &_Py_ID(add), task);
3702
0
    if (res == NULL) {
3703
0
        return NULL;
3704
0
    }
3705
0
    Py_DECREF(res);
3706
0
    Py_RETURN_NONE;
3707
0
}
3708
3709
/*[clinic input]
3710
_asyncio._register_eager_task
3711
3712
    task: object
3713
3714
Register a new task in asyncio as executed by loop.
3715
3716
Returns None.
3717
[clinic start generated code]*/
3718
3719
static PyObject *
3720
_asyncio__register_eager_task_impl(PyObject *module, PyObject *task)
3721
/*[clinic end generated code: output=dfe1d45367c73f1a input=237f684683398c51]*/
3722
0
{
3723
0
    asyncio_state *state = get_asyncio_state(module);
3724
3725
0
    if (Task_Check(state, task)) {
3726
        // task is an asyncio.Task instance or subclass, use efficient
3727
        // linked-list implementation.
3728
0
        _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3729
0
        register_task(ts, (TaskObj *)task);
3730
0
        Py_RETURN_NONE;
3731
0
    }
3732
3733
0
    if (PySet_Add(state->non_asyncio_eager_tasks, task) < 0) {
3734
0
        return NULL;
3735
0
    }
3736
3737
0
    Py_RETURN_NONE;
3738
0
}
3739
3740
3741
/*[clinic input]
3742
_asyncio._unregister_task
3743
3744
    task: object
3745
3746
Unregister a task.
3747
3748
Returns None.
3749
[clinic start generated code]*/
3750
3751
static PyObject *
3752
_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3753
/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
3754
0
{
3755
0
    asyncio_state *state = get_asyncio_state(module);
3756
0
    if (Task_Check(state, task)) {
3757
0
        unregister_task((TaskObj *)task);
3758
0
        Py_RETURN_NONE;
3759
0
    }
3760
0
    PyObject *res = PyObject_CallMethodOneArg(state->non_asyncio_tasks,
3761
0
                                              &_Py_ID(discard), task);
3762
0
    if (res == NULL) {
3763
0
        return NULL;
3764
0
    }
3765
0
    Py_DECREF(res);
3766
0
    Py_RETURN_NONE;
3767
0
}
3768
3769
/*[clinic input]
3770
_asyncio._unregister_eager_task
3771
3772
    task: object
3773
3774
Unregister a task.
3775
3776
Returns None.
3777
[clinic start generated code]*/
3778
3779
static PyObject *
3780
_asyncio__unregister_eager_task_impl(PyObject *module, PyObject *task)
3781
/*[clinic end generated code: output=a426922bd07f23d1 input=9d07401ef14ee048]*/
3782
0
{
3783
0
    asyncio_state *state = get_asyncio_state(module);
3784
0
    if (Task_Check(state, task)) {
3785
        // task is an asyncio.Task instance or subclass, use efficient
3786
        // linked-list implementation.
3787
0
        unregister_task((TaskObj *)task);
3788
0
        Py_RETURN_NONE;
3789
0
    }
3790
3791
0
    if (PySet_Discard(state->non_asyncio_eager_tasks, task) < 0) {
3792
0
        return NULL;
3793
0
    }
3794
3795
0
    Py_RETURN_NONE;
3796
0
}
3797
3798
3799
/*[clinic input]
3800
_asyncio._enter_task
3801
3802
    loop: object
3803
    task: object
3804
3805
Enter into task execution or resume suspended task.
3806
3807
Task belongs to loop.
3808
3809
Returns None.
3810
[clinic start generated code]*/
3811
3812
static PyObject *
3813
_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3814
/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3815
0
{
3816
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3817
0
    if (enter_task(ts, loop, task) < 0) {
3818
0
        return NULL;
3819
0
    }
3820
0
    Py_RETURN_NONE;
3821
0
}
3822
3823
3824
/*[clinic input]
3825
_asyncio._leave_task
3826
3827
    loop: object
3828
    task: object
3829
3830
Leave task execution or suspend a task.
3831
3832
Task belongs to loop.
3833
3834
Returns None.
3835
[clinic start generated code]*/
3836
3837
static PyObject *
3838
_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3839
/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3840
0
{
3841
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3842
0
    if (leave_task(ts, loop, task) < 0) {
3843
0
        return NULL;
3844
0
    }
3845
0
    Py_RETURN_NONE;
3846
0
}
3847
3848
3849
/*[clinic input]
3850
@permit_long_summary
3851
_asyncio._swap_current_task
3852
3853
    loop: object
3854
    task: object
3855
3856
Temporarily swap in the supplied task and return the original one (or None).
3857
3858
This is intended for use during eager coroutine execution.
3859
3860
[clinic start generated code]*/
3861
3862
static PyObject *
3863
_asyncio__swap_current_task_impl(PyObject *module, PyObject *loop,
3864
                                 PyObject *task)
3865
/*[clinic end generated code: output=9f88de958df74c7e input=ec14ed25855e3068]*/
3866
0
{
3867
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3868
0
    return swap_current_task(ts, loop, task);
3869
0
}
3870
3871
3872
/*[clinic input]
3873
_asyncio.current_task
3874
3875
    loop: object = None
3876
3877
Return a currently executed task.
3878
3879
[clinic start generated code]*/
3880
3881
static PyObject *
3882
_asyncio_current_task_impl(PyObject *module, PyObject *loop)
3883
/*[clinic end generated code: output=fe15ac331a7f981a input=58910f61a5627112]*/
3884
0
{
3885
0
    if (loop == Py_None) {
3886
0
        loop = _asyncio_get_running_loop_impl(module);
3887
0
        if (loop == NULL) {
3888
0
            return NULL;
3889
0
        }
3890
0
    } else {
3891
0
        Py_INCREF(loop);
3892
0
    }
3893
3894
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3895
    // Fast path for the current running loop of current thread
3896
    // no locking or stop the world pause is required
3897
0
    if (ts->asyncio_running_loop == loop) {
3898
0
        if (ts->asyncio_running_task != NULL) {
3899
0
            Py_DECREF(loop);
3900
0
            return Py_NewRef(ts->asyncio_running_task);
3901
0
        }
3902
0
        Py_DECREF(loop);
3903
0
        Py_RETURN_NONE;
3904
0
    }
3905
3906
0
    PyObject *ret = Py_None;
3907
    // Stop the world and traverse the per-thread current tasks
3908
    // and return the task if the loop matches
3909
0
    PyInterpreterState *interp = ts->base.interp;
3910
0
    _PyEval_StopTheWorld(interp);
3911
0
    _Py_FOR_EACH_TSTATE_BEGIN(interp, p) {
3912
0
        ts = (_PyThreadStateImpl *)p;
3913
0
        if (ts->asyncio_running_loop == loop) {
3914
0
            if (ts->asyncio_running_task != NULL) {
3915
0
                ret = Py_NewRef(ts->asyncio_running_task);
3916
0
            }
3917
0
            goto exit;
3918
0
        }
3919
0
    }
3920
0
exit:
3921
0
    _Py_FOR_EACH_TSTATE_END(interp);
3922
0
    _PyEval_StartTheWorld(interp);
3923
0
    Py_DECREF(loop);
3924
0
    return ret;
3925
0
}
3926
3927
3928
static inline int
3929
add_one_task(asyncio_state *state, PyObject *tasks, PyObject *task, PyObject *loop)
3930
0
{
3931
0
    assert(PySet_CheckExact(tasks));
3932
0
    if (Task_CheckExact(state, task)) {
3933
0
        int pending = 0;
3934
0
        Py_BEGIN_CRITICAL_SECTION(task);
3935
0
        pending = ((TaskObj *)task)->task_state == STATE_PENDING && ((TaskObj *)task)->task_loop == loop;
3936
0
        Py_END_CRITICAL_SECTION();
3937
0
        if (pending) {
3938
0
            if (PySet_Add(tasks, task) < 0) {
3939
0
                return -1;
3940
0
            }
3941
0
        }
3942
0
        return 0;
3943
0
    }
3944
3945
0
    PyObject *done = PyObject_CallMethodNoArgs(task, &_Py_ID(done));
3946
0
    if (done == NULL) {
3947
0
        return -1;
3948
0
    }
3949
0
    if (Py_IsTrue(done)) {
3950
0
        return 0;
3951
0
    }
3952
0
    Py_DECREF(done);
3953
0
    PyObject *task_loop = get_future_loop(state, task);
3954
0
    if (task_loop == NULL) {
3955
0
        return -1;
3956
0
    }
3957
0
    if (task_loop == loop) {
3958
0
        if (PySet_Add(tasks, task) < 0) {
3959
0
            Py_DECREF(task_loop);
3960
0
            return -1;
3961
0
        }
3962
0
    }
3963
0
    Py_DECREF(task_loop);
3964
0
    return 0;
3965
0
}
3966
3967
static inline int
3968
add_tasks_llist(struct llist_node *head, PyListObject *tasks)
3969
0
{
3970
0
    struct llist_node *node;
3971
0
    llist_for_each_safe(node, head) {
3972
0
        TaskObj *task = llist_data(node, TaskObj, task_node);
3973
0
        assert(task->task_state == STATE_PENDING);
3974
        // The linked list holds borrowed references to task
3975
        // as such it is possible that the task is concurrently
3976
        // deallocated while added to this list.
3977
        // To protect against concurrent deallocations,
3978
        // we first try to incref the task which would fail
3979
        // if it is concurrently getting deallocated in another thread,
3980
        // otherwise it gets added to the list.
3981
0
        if (_Py_TryIncref((PyObject *)task)) {
3982
0
            if (_PyList_AppendTakeRef(tasks, (PyObject *)task) < 0) {
3983
                // do not call any escaping calls here while the world is stopped.
3984
0
                return -1;
3985
0
            }
3986
0
        }
3987
0
    }
3988
0
    return 0;
3989
0
}
3990
3991
static inline int
3992
add_tasks_interp(PyInterpreterState *interp, PyListObject *tasks)
3993
0
{
3994
#ifdef Py_GIL_DISABLED
3995
    assert(interp->stoptheworld.world_stopped);
3996
#endif
3997
    // Start traversing from interpreter's linked list
3998
0
    struct llist_node *head = &interp->asyncio_tasks_head;
3999
4000
0
    if (add_tasks_llist(head, tasks) < 0) {
4001
0
        return -1;
4002
0
    }
4003
4004
0
    int ret = 0;
4005
    // traverse the task lists of thread states
4006
0
    _Py_FOR_EACH_TSTATE_BEGIN(interp, p) {
4007
0
        _PyThreadStateImpl *ts = (_PyThreadStateImpl *)p;
4008
0
        head = &ts->asyncio_tasks_head;
4009
0
        if (add_tasks_llist(head, tasks) < 0) {
4010
0
            ret = -1;
4011
0
            goto exit;
4012
0
        }
4013
0
    }
4014
0
exit:
4015
0
    _Py_FOR_EACH_TSTATE_END(interp);
4016
0
    return ret;
4017
0
}
4018
4019
/*********************** Module **************************/
4020
4021
/*[clinic input]
4022
_asyncio.all_tasks
4023
4024
    loop: object = None
4025
4026
Return a set of all tasks for the loop.
4027
4028
[clinic start generated code]*/
4029
4030
static PyObject *
4031
_asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
4032
/*[clinic end generated code: output=0e107cbb7f72aa7b input=43a1b423c2d95bfa]*/
4033
0
{
4034
0
    asyncio_state *state = get_asyncio_state(module);
4035
0
    if (loop == Py_None) {
4036
0
        loop = _asyncio_get_running_loop_impl(module);
4037
0
        if (loop == NULL) {
4038
0
            return NULL;
4039
0
        }
4040
0
    } else {
4041
0
        Py_INCREF(loop);
4042
0
    }
4043
    // First add eager tasks to the list so that we don't miss
4044
    // any tasks which graduates from eager to non-eager
4045
    // We first add all the tasks to `tasks` list and then filter
4046
    // out the tasks which are done and return it as a set.
4047
0
    PyObject *tasks = PyList_New(0);
4048
0
    if (tasks == NULL) {
4049
0
        Py_DECREF(loop);
4050
0
        return NULL;
4051
0
    }
4052
0
    if (PyList_Extend(tasks, state->non_asyncio_eager_tasks) < 0) {
4053
0
        Py_DECREF(tasks);
4054
0
        Py_DECREF(loop);
4055
0
        return NULL;
4056
0
    }
4057
0
    if (PyList_Extend(tasks, state->non_asyncio_tasks) < 0) {
4058
0
        Py_DECREF(tasks);
4059
0
        Py_DECREF(loop);
4060
0
        return NULL;
4061
0
    }
4062
4063
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
4064
0
    if (ts->asyncio_running_loop == loop) {
4065
        // Fast path for the current running loop of current thread
4066
        // no locking or stop the world pause is required
4067
0
        struct llist_node *head = &ts->asyncio_tasks_head;
4068
0
        if (add_tasks_llist(head, (PyListObject *)tasks) < 0) {
4069
0
            Py_DECREF(tasks);
4070
0
            Py_DECREF(loop);
4071
0
            return NULL;
4072
0
        }
4073
0
    }
4074
0
    else {
4075
        // Slow path for loop running in different thread
4076
0
        PyInterpreterState *interp = ts->base.interp;
4077
        // Stop the world and traverse the per-thread linked list
4078
        // of asyncio tasks for every thread, as well as the
4079
        // interpreter's linked list, and add them to `tasks`.
4080
        // The interpreter linked list is used for any lingering tasks
4081
        // whose thread state has been deallocated while the task was
4082
        // still alive. This can happen if a task is referenced by
4083
        // a different thread, in which case the task is moved to
4084
        // the interpreter's linked list from the thread's linked
4085
        // list before deallocation. See PyThreadState_Clear.
4086
        //
4087
        // The stop-the-world pause is required so that no thread
4088
        // modifies its linked list while being iterated here
4089
        // in parallel. This design allows for lock-free
4090
        // register_task/unregister_task for loops running in parallel
4091
        // in different threads (the general case).
4092
0
        _PyEval_StopTheWorld(interp);
4093
0
        int ret = add_tasks_interp(interp, (PyListObject *)tasks);
4094
0
        _PyEval_StartTheWorld(interp);
4095
0
        if (ret < 0) {
4096
            // call any escaping calls after starting the world to avoid any deadlocks.
4097
0
            Py_DECREF(tasks);
4098
0
            Py_DECREF(loop);
4099
0
            return NULL;
4100
0
        }
4101
0
    }
4102
4103
    // All the tasks are now in the list, now filter the tasks which are done
4104
0
    PyObject *res = PySet_New(NULL);
4105
0
    if (res == NULL) {
4106
0
        Py_DECREF(tasks);
4107
0
        Py_DECREF(loop);
4108
0
        return NULL;
4109
0
    }
4110
4111
0
    for (Py_ssize_t i = 0; i < PyList_GET_SIZE(tasks); i++) {
4112
0
        PyObject *task = PyList_GET_ITEM(tasks, i);
4113
0
        if (add_one_task(state, res, task, loop) < 0) {
4114
0
            Py_DECREF(res);
4115
0
            Py_DECREF(tasks);
4116
0
            Py_DECREF(loop);
4117
0
            return NULL;
4118
0
        }
4119
0
    }
4120
4121
0
    Py_DECREF(tasks);
4122
0
    Py_DECREF(loop);
4123
0
    return res;
4124
0
}
4125
4126
/*[clinic input]
4127
_asyncio.future_add_to_awaited_by
4128
4129
    fut: object
4130
    waiter: object
4131
    /
4132
4133
Record that `fut` is awaited on by `waiter`.
4134
4135
[clinic start generated code]*/
4136
4137
static PyObject *
4138
_asyncio_future_add_to_awaited_by_impl(PyObject *module, PyObject *fut,
4139
                                       PyObject *waiter)
4140
/*[clinic end generated code: output=0ab9a1a63389e4df input=06e6eaac51f532b9]*/
4141
0
{
4142
0
    asyncio_state *state = get_asyncio_state(module);
4143
0
    if (TaskOrFuture_Check(state, fut) && TaskOrFuture_Check(state, waiter)) {
4144
0
        int res;
4145
0
        Py_BEGIN_CRITICAL_SECTION(fut);
4146
0
        res = future_awaited_by_add(state, (FutureObj *)fut, waiter);
4147
0
        Py_END_CRITICAL_SECTION();
4148
0
        if (res) {
4149
0
            return NULL;
4150
0
        }
4151
0
    }
4152
0
    Py_RETURN_NONE;
4153
0
}
4154
4155
/*[clinic input]
4156
_asyncio.future_discard_from_awaited_by
4157
4158
    fut: object
4159
    waiter: object
4160
    /
4161
4162
[clinic start generated code]*/
4163
4164
static PyObject *
4165
_asyncio_future_discard_from_awaited_by_impl(PyObject *module, PyObject *fut,
4166
                                             PyObject *waiter)
4167
/*[clinic end generated code: output=a03b0b4323b779de input=3833f7639e88e483]*/
4168
0
{
4169
0
    asyncio_state *state = get_asyncio_state(module);
4170
0
    if (TaskOrFuture_Check(state, fut) && TaskOrFuture_Check(state, waiter)) {
4171
0
        int res;
4172
0
        Py_BEGIN_CRITICAL_SECTION(fut);
4173
0
        res = future_awaited_by_discard(state, (FutureObj *)fut, waiter);
4174
0
        Py_END_CRITICAL_SECTION();
4175
0
        if (res) {
4176
0
            return NULL;
4177
0
        }
4178
0
    }
4179
0
    Py_RETURN_NONE;
4180
0
}
4181
4182
static int
4183
module_traverse(PyObject *mod, visitproc visit, void *arg)
4184
0
{
4185
0
    asyncio_state *state = get_asyncio_state(mod);
4186
4187
0
    Py_VISIT(state->FutureIterType);
4188
0
    Py_VISIT(state->TaskStepMethWrapper_Type);
4189
0
    Py_VISIT(state->FutureType);
4190
0
    Py_VISIT(state->TaskType);
4191
4192
0
    Py_VISIT(state->asyncio_mod);
4193
0
    Py_VISIT(state->traceback_extract_stack);
4194
0
    Py_VISIT(state->asyncio_future_repr_func);
4195
0
    Py_VISIT(state->asyncio_get_event_loop_policy);
4196
0
    Py_VISIT(state->asyncio_iscoroutine_func);
4197
0
    Py_VISIT(state->asyncio_task_get_stack_func);
4198
0
    Py_VISIT(state->asyncio_task_print_stack_func);
4199
0
    Py_VISIT(state->asyncio_task_repr_func);
4200
0
    Py_VISIT(state->asyncio_InvalidStateError);
4201
0
    Py_VISIT(state->asyncio_CancelledError);
4202
4203
0
    Py_VISIT(state->non_asyncio_tasks);
4204
0
    Py_VISIT(state->non_asyncio_eager_tasks);
4205
0
    Py_VISIT(state->iscoroutine_typecache);
4206
4207
0
    Py_VISIT(state->context_kwname);
4208
4209
0
    return 0;
4210
0
}
4211
4212
static int
4213
module_clear(PyObject *mod)
4214
0
{
4215
0
    asyncio_state *state = get_asyncio_state(mod);
4216
4217
0
    Py_CLEAR(state->FutureIterType);
4218
0
    Py_CLEAR(state->TaskStepMethWrapper_Type);
4219
0
    Py_CLEAR(state->FutureType);
4220
0
    Py_CLEAR(state->TaskType);
4221
4222
0
    Py_CLEAR(state->asyncio_mod);
4223
0
    Py_CLEAR(state->traceback_extract_stack);
4224
0
    Py_CLEAR(state->asyncio_future_repr_func);
4225
0
    Py_CLEAR(state->asyncio_get_event_loop_policy);
4226
0
    Py_CLEAR(state->asyncio_iscoroutine_func);
4227
0
    Py_CLEAR(state->asyncio_task_get_stack_func);
4228
0
    Py_CLEAR(state->asyncio_task_print_stack_func);
4229
0
    Py_CLEAR(state->asyncio_task_repr_func);
4230
0
    Py_CLEAR(state->asyncio_InvalidStateError);
4231
0
    Py_CLEAR(state->asyncio_CancelledError);
4232
4233
0
    Py_CLEAR(state->non_asyncio_tasks);
4234
0
    Py_CLEAR(state->non_asyncio_eager_tasks);
4235
0
    Py_CLEAR(state->iscoroutine_typecache);
4236
4237
0
    Py_CLEAR(state->context_kwname);
4238
    // Clear the ref to running loop so that finalizers can run early.
4239
    // If there are other running loops in different threads,
4240
    // those get cleared in PyThreadState_Clear.
4241
0
    _PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
4242
0
    Py_CLEAR(ts->asyncio_running_loop);
4243
0
    Py_CLEAR(ts->asyncio_running_task);
4244
4245
0
    return 0;
4246
0
}
4247
4248
static void
4249
module_free(void *mod)
4250
0
{
4251
0
    (void)module_clear((PyObject *)mod);
4252
0
}
4253
4254
static int
4255
module_init(asyncio_state *state)
4256
0
{
4257
0
    PyObject *module = NULL;
4258
4259
0
    state->asyncio_mod = PyImport_ImportModule("asyncio");
4260
0
    if (state->asyncio_mod == NULL) {
4261
0
        goto fail;
4262
0
    }
4263
4264
0
    state->iscoroutine_typecache = PySet_New(NULL);
4265
0
    if (state->iscoroutine_typecache == NULL) {
4266
0
        goto fail;
4267
0
    }
4268
4269
0
    state->context_kwname = Py_BuildValue("(s)", "context");
4270
0
    if (state->context_kwname == NULL) {
4271
0
        goto fail;
4272
0
    }
4273
4274
0
#define WITH_MOD(NAME) \
4275
0
    Py_CLEAR(module); \
4276
0
    module = PyImport_ImportModule(NAME); \
4277
0
    if (module == NULL) { \
4278
0
        goto fail; \
4279
0
    }
4280
4281
0
#define GET_MOD_ATTR(VAR, NAME) \
4282
0
    VAR = PyObject_GetAttrString(module, NAME); \
4283
0
    if (VAR == NULL) { \
4284
0
        goto fail; \
4285
0
    }
4286
4287
0
    WITH_MOD("asyncio.events")
4288
0
    GET_MOD_ATTR(state->asyncio_get_event_loop_policy, "_get_event_loop_policy")
4289
4290
0
    WITH_MOD("asyncio.base_futures")
4291
0
    GET_MOD_ATTR(state->asyncio_future_repr_func, "_future_repr")
4292
4293
0
    WITH_MOD("asyncio.exceptions")
4294
0
    GET_MOD_ATTR(state->asyncio_InvalidStateError, "InvalidStateError")
4295
0
    GET_MOD_ATTR(state->asyncio_CancelledError, "CancelledError")
4296
4297
0
    WITH_MOD("asyncio.base_tasks")
4298
0
    GET_MOD_ATTR(state->asyncio_task_repr_func, "_task_repr")
4299
0
    GET_MOD_ATTR(state->asyncio_task_get_stack_func, "_task_get_stack")
4300
0
    GET_MOD_ATTR(state->asyncio_task_print_stack_func, "_task_print_stack")
4301
4302
0
    WITH_MOD("asyncio.coroutines")
4303
0
    GET_MOD_ATTR(state->asyncio_iscoroutine_func, "iscoroutine")
4304
4305
0
    WITH_MOD("traceback")
4306
0
    GET_MOD_ATTR(state->traceback_extract_stack, "extract_stack")
4307
4308
0
    PyObject *weak_set;
4309
0
    WITH_MOD("weakref")
4310
0
    GET_MOD_ATTR(weak_set, "WeakSet");
4311
0
    state->non_asyncio_tasks = PyObject_CallNoArgs(weak_set);
4312
0
    Py_CLEAR(weak_set);
4313
0
    if (state->non_asyncio_tasks == NULL) {
4314
0
        goto fail;
4315
0
    }
4316
4317
0
    state->non_asyncio_eager_tasks = PySet_New(NULL);
4318
0
    if (state->non_asyncio_eager_tasks == NULL) {
4319
0
        goto fail;
4320
0
    }
4321
4322
0
    state->debug_offsets = &_Py_AsyncioDebug;
4323
4324
0
    Py_DECREF(module);
4325
0
    return 0;
4326
4327
0
fail:
4328
0
    Py_CLEAR(module);
4329
0
    return -1;
4330
4331
0
#undef WITH_MOD
4332
0
#undef GET_MOD_ATTR
4333
0
}
4334
4335
PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
4336
4337
static PyMethodDef asyncio_methods[] = {
4338
    _ASYNCIO_CURRENT_TASK_METHODDEF
4339
    _ASYNCIO_GET_EVENT_LOOP_METHODDEF
4340
    _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
4341
    _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
4342
    _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
4343
    _ASYNCIO__REGISTER_TASK_METHODDEF
4344
    _ASYNCIO__REGISTER_EAGER_TASK_METHODDEF
4345
    _ASYNCIO__UNREGISTER_TASK_METHODDEF
4346
    _ASYNCIO__UNREGISTER_EAGER_TASK_METHODDEF
4347
    _ASYNCIO__ENTER_TASK_METHODDEF
4348
    _ASYNCIO__LEAVE_TASK_METHODDEF
4349
    _ASYNCIO__SWAP_CURRENT_TASK_METHODDEF
4350
    _ASYNCIO_ALL_TASKS_METHODDEF
4351
    _ASYNCIO_FUTURE_ADD_TO_AWAITED_BY_METHODDEF
4352
    _ASYNCIO_FUTURE_DISCARD_FROM_AWAITED_BY_METHODDEF
4353
    {NULL, NULL}
4354
};
4355
4356
static int
4357
module_exec(PyObject *mod)
4358
0
{
4359
0
    asyncio_state *state = get_asyncio_state(mod);
4360
4361
4362
0
#define CREATE_TYPE(m, tp, spec, base)                                  \
4363
0
    do {                                                                \
4364
0
        tp = (PyTypeObject *)PyType_FromMetaclass(NULL, m, spec,        \
4365
0
                                                  (PyObject *)base);    \
4366
0
        if (tp == NULL) {                                               \
4367
0
            return -1;                                                  \
4368
0
        }                                                               \
4369
0
    } while (0)
4370
4371
0
    CREATE_TYPE(mod, state->TaskStepMethWrapper_Type, &TaskStepMethWrapper_spec, NULL);
4372
0
    CREATE_TYPE(mod, state->FutureIterType, &FutureIter_spec, NULL);
4373
0
    CREATE_TYPE(mod, state->FutureType, &Future_spec, NULL);
4374
0
    CREATE_TYPE(mod, state->TaskType, &Task_spec, state->FutureType);
4375
4376
0
#undef CREATE_TYPE
4377
4378
0
    if (PyModule_AddType(mod, state->FutureType) < 0) {
4379
0
        return -1;
4380
0
    }
4381
4382
0
    if (PyModule_AddType(mod, state->TaskType) < 0) {
4383
0
        return -1;
4384
0
    }
4385
    // Must be done after types are added to avoid a circular dependency
4386
0
    if (module_init(state) < 0) {
4387
0
        return -1;
4388
0
    }
4389
4390
0
    return 0;
4391
0
}
4392
4393
static struct PyModuleDef_Slot module_slots[] = {
4394
    _Py_ABI_SLOT,
4395
    {Py_mod_exec, module_exec},
4396
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
4397
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
4398
    {0, NULL},
4399
};
4400
4401
static struct PyModuleDef _asynciomodule = {
4402
    .m_base = PyModuleDef_HEAD_INIT,
4403
    .m_name = "_asyncio",
4404
    .m_doc = module_doc,
4405
    .m_size = sizeof(asyncio_state),
4406
    .m_methods = asyncio_methods,
4407
    .m_slots = module_slots,
4408
    .m_traverse = module_traverse,
4409
    .m_clear = module_clear,
4410
    .m_free = module_free,
4411
};
4412
4413
PyMODINIT_FUNC
4414
PyInit__asyncio(void)
4415
0
{
4416
0
    return PyModuleDef_Init(&_asynciomodule);
4417
0
}