Coverage Report

Created: 2026-04-12 06:54

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