Coverage Report

Created: 2025-12-14 07:06

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