Coverage Report

Created: 2026-10-31 06:21

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