Coverage Report

Created: 2026-07-14 06:16

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