Coverage Report

Created: 2026-01-10 06:41

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