Coverage Report

Created: 2025-07-18 06:09

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