1 #include "Python.h"
2 #include "pycore_pyerrors.h"      // _PyErr_ClearExcState()
3 #include <stddef.h>               // offsetof()
4 
5 
6 /*[clinic input]
7 module _asyncio
8 [clinic start generated code]*/
9 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
10 
11 
12 /* identifiers used from some functions */
13 _Py_IDENTIFIER(__asyncio_running_event_loop__);
14 _Py_IDENTIFIER(_asyncio_future_blocking);
15 _Py_IDENTIFIER(add_done_callback);
16 _Py_IDENTIFIER(call_soon);
17 _Py_IDENTIFIER(cancel);
18 _Py_IDENTIFIER(get_event_loop);
19 _Py_IDENTIFIER(send);
20 _Py_IDENTIFIER(throw);
21 
22 
23 /* State of the _asyncio module */
24 static PyObject *asyncio_mod;
25 static PyObject *traceback_extract_stack;
26 static PyObject *asyncio_get_event_loop_policy;
27 static PyObject *asyncio_future_repr_info_func;
28 static PyObject *asyncio_iscoroutine_func;
29 static PyObject *asyncio_task_get_stack_func;
30 static PyObject *asyncio_task_print_stack_func;
31 static PyObject *asyncio_task_repr_info_func;
32 static PyObject *asyncio_InvalidStateError;
33 static PyObject *asyncio_CancelledError;
34 static PyObject *context_kwname;
35 static int module_initialized;
36 
37 static PyObject *cached_running_holder;
38 static volatile uint64_t cached_running_holder_tsid;
39 
40 /* Counter for autogenerated Task names */
41 static uint64_t task_name_counter = 0;
42 
43 /* WeakSet containing all alive tasks. */
44 static PyObject *all_tasks;
45 
46 /* Dictionary containing tasks that are currently active in
47    all running event loops.  {EventLoop: Task} */
48 static PyObject *current_tasks;
49 
50 /* An isinstance type cache for the 'is_coroutine()' function. */
51 static PyObject *iscoroutine_typecache;
52 
53 
54 typedef enum {
55     STATE_PENDING,
56     STATE_CANCELLED,
57     STATE_FINISHED
58 } fut_state;
59 
60 #define FutureObj_HEAD(prefix)                                              \
61     PyObject_HEAD                                                           \
62     PyObject *prefix##_loop;                                                \
63     PyObject *prefix##_callback0;                                           \
64     PyObject *prefix##_context0;                                            \
65     PyObject *prefix##_callbacks;                                           \
66     PyObject *prefix##_exception;                                           \
67     PyObject *prefix##_result;                                              \
68     PyObject *prefix##_source_tb;                                           \
69     PyObject *prefix##_cancel_msg;                                          \
70     fut_state prefix##_state;                                               \
71     int prefix##_log_tb;                                                    \
72     int prefix##_blocking;                                                  \
73     PyObject *dict;                                                         \
74     PyObject *prefix##_weakreflist;                                         \
75     _PyErr_StackItem prefix##_cancelled_exc_state;
76 
77 typedef struct {
78     FutureObj_HEAD(fut)
79 } FutureObj;
80 
81 typedef struct {
82     FutureObj_HEAD(task)
83     PyObject *task_fut_waiter;
84     PyObject *task_coro;
85     PyObject *task_name;
86     PyObject *task_context;
87     int task_must_cancel;
88     int task_log_destroy_pending;
89 } TaskObj;
90 
91 typedef struct {
92     PyObject_HEAD
93     TaskObj *sw_task;
94     PyObject *sw_arg;
95 } TaskStepMethWrapper;
96 
97 typedef struct {
98     PyObject_HEAD
99     TaskObj *ww_task;
100 } TaskWakeupMethWrapper;
101 
102 typedef struct {
103     PyObject_HEAD
104     PyObject *rl_loop;
105 #if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
106     pid_t rl_pid;
107 #endif
108 } PyRunningLoopHolder;
109 
110 
111 static PyTypeObject FutureType;
112 static PyTypeObject TaskType;
113 static PyTypeObject PyRunningLoopHolder_Type;
114 
115 
116 #define Future_CheckExact(obj) Py_IS_TYPE(obj, &FutureType)
117 #define Task_CheckExact(obj) Py_IS_TYPE(obj, &TaskType)
118 
119 #define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
120 #define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
121 
122 #include "clinic/_asynciomodule.c.h"
123 
124 
125 /*[clinic input]
126 class _asyncio.Future "FutureObj *" "&Future_Type"
127 [clinic start generated code]*/
128 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
129 
130 
131 /* Get FutureIter from Future */
132 static PyObject * future_new_iter(PyObject *);
133 
134 static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
135 
136 
137 static int
_is_coroutine(PyObject * coro)138 _is_coroutine(PyObject *coro)
139 {
140     /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
141        to check if it's another coroutine flavour.
142 
143        Do this check after 'future_init()'; in case we need to raise
144        an error, __del__ needs a properly initialized object.
145     */
146     PyObject *res = PyObject_CallOneArg(asyncio_iscoroutine_func, coro);
147     if (res == NULL) {
148         return -1;
149     }
150 
151     int is_res_true = PyObject_IsTrue(res);
152     Py_DECREF(res);
153     if (is_res_true <= 0) {
154         return is_res_true;
155     }
156 
157     if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
158         /* Just in case we don't want to cache more than 100
159            positive types.  That shouldn't ever happen, unless
160            someone stressing the system on purpose.
161         */
162         if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
163             return -1;
164         }
165     }
166 
167     return 1;
168 }
169 
170 
171 static inline int
is_coroutine(PyObject * coro)172 is_coroutine(PyObject *coro)
173 {
174     if (PyCoro_CheckExact(coro)) {
175         return 1;
176     }
177 
178     /* Check if `type(coro)` is in the cache.
179        Caching makes is_coroutine() function almost as fast as
180        PyCoro_CheckExact() for non-native coroutine-like objects
181        (like coroutines compiled with Cython).
182 
183        asyncio.iscoroutine() has its own type caching mechanism.
184        This cache allows us to avoid the cost of even calling
185        a pure-Python function in 99.9% cases.
186     */
187     int has_it = PySet_Contains(
188         iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
189     if (has_it == 0) {
190         /* type(coro) is not in iscoroutine_typecache */
191         return _is_coroutine(coro);
192     }
193 
194     /* either an error has occurred or
195        type(coro) is in iscoroutine_typecache
196     */
197     return has_it;
198 }
199 
200 
201 static PyObject *
get_future_loop(PyObject * fut)202 get_future_loop(PyObject *fut)
203 {
204     /* Implementation of `asyncio.futures._get_loop` */
205 
206     _Py_IDENTIFIER(get_loop);
207     _Py_IDENTIFIER(_loop);
208     PyObject *getloop;
209 
210     if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
211         PyObject *loop = ((FutureObj *)fut)->fut_loop;
212         Py_INCREF(loop);
213         return loop;
214     }
215 
216     if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
217         return NULL;
218     }
219     if (getloop != NULL) {
220         PyObject *res = PyObject_CallNoArgs(getloop);
221         Py_DECREF(getloop);
222         return res;
223     }
224 
225     return _PyObject_GetAttrId(fut, &PyId__loop);
226 }
227 
228 
229 static int
get_running_loop(PyObject ** loop)230 get_running_loop(PyObject **loop)
231 {
232     PyObject *rl;
233 
234     PyThreadState *ts = PyThreadState_Get();
235     uint64_t ts_id = PyThreadState_GetID(ts);
236     if (ts_id == cached_running_holder_tsid && cached_running_holder != NULL) {
237         // Fast path, check the cache.
238         rl = cached_running_holder;  // borrowed
239     }
240     else {
241         PyObject *ts_dict = _PyThreadState_GetDict(ts);  // borrowed
242         if (ts_dict == NULL) {
243             goto not_found;
244         }
245 
246         rl = _PyDict_GetItemIdWithError(
247             ts_dict, &PyId___asyncio_running_event_loop__);  // borrowed
248         if (rl == NULL) {
249             if (PyErr_Occurred()) {
250                 goto error;
251             }
252             else {
253                 goto not_found;
254             }
255         }
256 
257         cached_running_holder = rl;  // borrowed
258         cached_running_holder_tsid = ts_id;
259     }
260 
261     assert(Py_IS_TYPE(rl, &PyRunningLoopHolder_Type));
262     PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
263 
264     if (running_loop == Py_None) {
265         goto not_found;
266     }
267 
268 #if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
269     /* On Windows there is no getpid, but there is also no os.fork(),
270        so there is no need for this check.
271     */
272     if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
273         goto not_found;
274     }
275 #endif
276 
277     Py_INCREF(running_loop);
278     *loop = running_loop;
279     return 0;
280 
281 not_found:
282     *loop = NULL;
283     return 0;
284 
285 error:
286     *loop = NULL;
287     return -1;
288 }
289 
290 
291 static int
set_running_loop(PyObject * loop)292 set_running_loop(PyObject *loop)
293 {
294     PyObject *ts_dict = NULL;
295 
296     PyThreadState *tstate = PyThreadState_Get();
297     if (tstate != NULL) {
298         ts_dict = _PyThreadState_GetDict(tstate);  // borrowed
299     }
300 
301     if (ts_dict == NULL) {
302         PyErr_SetString(
303             PyExc_RuntimeError, "thread-local storage is not available");
304         return -1;
305     }
306 
307     PyRunningLoopHolder *rl = new_running_loop_holder(loop);
308     if (rl == NULL) {
309         return -1;
310     }
311 
312     if (_PyDict_SetItemId(
313             ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
314     {
315         Py_DECREF(rl);  // will cleanup loop & current_pid
316         return -1;
317     }
318     Py_DECREF(rl);
319 
320     cached_running_holder = (PyObject *)rl;
321     cached_running_holder_tsid = PyThreadState_GetID(tstate);
322 
323     return 0;
324 }
325 
326 
327 static PyObject *
get_event_loop(void)328 get_event_loop(void)
329 {
330     PyObject *loop;
331     PyObject *policy;
332 
333     if (get_running_loop(&loop)) {
334         return NULL;
335     }
336     if (loop != NULL) {
337         return loop;
338     }
339 
340     policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy);
341     if (policy == NULL) {
342         return NULL;
343     }
344 
345     loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
346     Py_DECREF(policy);
347     return loop;
348 }
349 
350 
351 static int
call_soon(PyObject * loop,PyObject * func,PyObject * arg,PyObject * ctx)352 call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
353 {
354     PyObject *handle;
355     PyObject *stack[3];
356     Py_ssize_t nargs;
357 
358     if (ctx == NULL) {
359         handle = _PyObject_CallMethodIdObjArgs(
360             loop, &PyId_call_soon, func, arg, NULL);
361     }
362     else {
363         /* Use FASTCALL to pass a keyword-only argument to call_soon */
364 
365         PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
366         if (callable == NULL) {
367             return -1;
368         }
369 
370         /* All refs in 'stack' are borrowed. */
371         nargs = 1;
372         stack[0] = func;
373         if (arg != NULL) {
374             stack[1] = arg;
375             nargs++;
376         }
377         stack[nargs] = (PyObject *)ctx;
378 
379         handle = PyObject_Vectorcall(callable, stack, nargs, context_kwname);
380         Py_DECREF(callable);
381     }
382 
383     if (handle == NULL) {
384         return -1;
385     }
386     Py_DECREF(handle);
387     return 0;
388 }
389 
390 
391 static inline int
future_is_alive(FutureObj * fut)392 future_is_alive(FutureObj *fut)
393 {
394     return fut->fut_loop != NULL;
395 }
396 
397 
398 static inline int
future_ensure_alive(FutureObj * fut)399 future_ensure_alive(FutureObj *fut)
400 {
401     if (!future_is_alive(fut)) {
402         PyErr_SetString(PyExc_RuntimeError,
403                         "Future object is not initialized.");
404         return -1;
405     }
406     return 0;
407 }
408 
409 
410 #define ENSURE_FUTURE_ALIVE(fut)                                \
411     do {                                                        \
412         assert(Future_Check(fut) || Task_Check(fut));           \
413         if (future_ensure_alive((FutureObj*)fut)) {             \
414             return NULL;                                        \
415         }                                                       \
416     } while(0);
417 
418 
419 static int
future_schedule_callbacks(FutureObj * fut)420 future_schedule_callbacks(FutureObj *fut)
421 {
422     Py_ssize_t len;
423     Py_ssize_t i;
424 
425     if (fut->fut_callback0 != NULL) {
426         /* There's a 1st callback */
427 
428         int ret = call_soon(
429             fut->fut_loop, fut->fut_callback0,
430             (PyObject *)fut, fut->fut_context0);
431 
432         Py_CLEAR(fut->fut_callback0);
433         Py_CLEAR(fut->fut_context0);
434         if (ret) {
435             /* If an error occurs in pure-Python implementation,
436                all callbacks are cleared. */
437             Py_CLEAR(fut->fut_callbacks);
438             return ret;
439         }
440 
441         /* we called the first callback, now try calling
442            callbacks from the 'fut_callbacks' list. */
443     }
444 
445     if (fut->fut_callbacks == NULL) {
446         /* No more callbacks, return. */
447         return 0;
448     }
449 
450     len = PyList_GET_SIZE(fut->fut_callbacks);
451     if (len == 0) {
452         /* The list of callbacks was empty; clear it and return. */
453         Py_CLEAR(fut->fut_callbacks);
454         return 0;
455     }
456 
457     for (i = 0; i < len; i++) {
458         PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
459         PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
460         PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
461 
462         if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
463             /* If an error occurs in pure-Python implementation,
464                all callbacks are cleared. */
465             Py_CLEAR(fut->fut_callbacks);
466             return -1;
467         }
468     }
469 
470     Py_CLEAR(fut->fut_callbacks);
471     return 0;
472 }
473 
474 
475 static int
future_init(FutureObj * fut,PyObject * loop)476 future_init(FutureObj *fut, PyObject *loop)
477 {
478     PyObject *res;
479     int is_true;
480     _Py_IDENTIFIER(get_debug);
481 
482     // Same to FutureObj_clear() but not clearing fut->dict
483     Py_CLEAR(fut->fut_loop);
484     Py_CLEAR(fut->fut_callback0);
485     Py_CLEAR(fut->fut_context0);
486     Py_CLEAR(fut->fut_callbacks);
487     Py_CLEAR(fut->fut_result);
488     Py_CLEAR(fut->fut_exception);
489     Py_CLEAR(fut->fut_source_tb);
490     Py_CLEAR(fut->fut_cancel_msg);
491     _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
492 
493     fut->fut_state = STATE_PENDING;
494     fut->fut_log_tb = 0;
495     fut->fut_blocking = 0;
496 
497     if (loop == Py_None) {
498         loop = get_event_loop();
499         if (loop == NULL) {
500             return -1;
501         }
502     }
503     else {
504         Py_INCREF(loop);
505     }
506     fut->fut_loop = loop;
507 
508     res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
509     if (res == NULL) {
510         return -1;
511     }
512     is_true = PyObject_IsTrue(res);
513     Py_DECREF(res);
514     if (is_true < 0) {
515         return -1;
516     }
517     if (is_true && !_Py_IsFinalizing()) {
518         /* Only try to capture the traceback if the interpreter is not being
519            finalized.  The original motivation to add a `_Py_IsFinalizing()`
520            call was to prevent SIGSEGV when a Future is created in a __del__
521            method, which is called during the interpreter shutdown and the
522            traceback module is already unloaded.
523         */
524         fut->fut_source_tb = PyObject_CallNoArgs(traceback_extract_stack);
525         if (fut->fut_source_tb == NULL) {
526             return -1;
527         }
528     }
529 
530     return 0;
531 }
532 
533 static PyObject *
future_set_result(FutureObj * fut,PyObject * res)534 future_set_result(FutureObj *fut, PyObject *res)
535 {
536     if (future_ensure_alive(fut)) {
537         return NULL;
538     }
539 
540     if (fut->fut_state != STATE_PENDING) {
541         PyErr_SetString(asyncio_InvalidStateError, "invalid state");
542         return NULL;
543     }
544 
545     assert(!fut->fut_result);
546     Py_INCREF(res);
547     fut->fut_result = res;
548     fut->fut_state = STATE_FINISHED;
549 
550     if (future_schedule_callbacks(fut) == -1) {
551         return NULL;
552     }
553     Py_RETURN_NONE;
554 }
555 
556 static PyObject *
future_set_exception(FutureObj * fut,PyObject * exc)557 future_set_exception(FutureObj *fut, PyObject *exc)
558 {
559     PyObject *exc_val = NULL;
560 
561     if (fut->fut_state != STATE_PENDING) {
562         PyErr_SetString(asyncio_InvalidStateError, "invalid state");
563         return NULL;
564     }
565 
566     if (PyExceptionClass_Check(exc)) {
567         exc_val = PyObject_CallNoArgs(exc);
568         if (exc_val == NULL) {
569             return NULL;
570         }
571         if (fut->fut_state != STATE_PENDING) {
572             Py_DECREF(exc_val);
573             PyErr_SetString(asyncio_InvalidStateError, "invalid state");
574             return NULL;
575         }
576     }
577     else {
578         exc_val = exc;
579         Py_INCREF(exc_val);
580     }
581     if (!PyExceptionInstance_Check(exc_val)) {
582         Py_DECREF(exc_val);
583         PyErr_SetString(PyExc_TypeError, "invalid exception object");
584         return NULL;
585     }
586     if (Py_IS_TYPE(exc_val, (PyTypeObject *)PyExc_StopIteration)) {
587         Py_DECREF(exc_val);
588         PyErr_SetString(PyExc_TypeError,
589                         "StopIteration interacts badly with generators "
590                         "and cannot be raised into a Future");
591         return NULL;
592     }
593 
594     assert(!fut->fut_exception);
595     fut->fut_exception = exc_val;
596     fut->fut_state = STATE_FINISHED;
597 
598     if (future_schedule_callbacks(fut) == -1) {
599         return NULL;
600     }
601 
602     fut->fut_log_tb = 1;
603     Py_RETURN_NONE;
604 }
605 
606 static PyObject *
create_cancelled_error(PyObject * msg)607 create_cancelled_error(PyObject *msg)
608 {
609     PyObject *exc;
610     if (msg == NULL || msg == Py_None) {
611         exc = PyObject_CallNoArgs(asyncio_CancelledError);
612     } else {
613         exc = PyObject_CallOneArg(asyncio_CancelledError, msg);
614     }
615     return exc;
616 }
617 
618 static void
future_set_cancelled_error(FutureObj * fut)619 future_set_cancelled_error(FutureObj *fut)
620 {
621     PyObject *exc = create_cancelled_error(fut->fut_cancel_msg);
622     PyErr_SetObject(asyncio_CancelledError, exc);
623     Py_DECREF(exc);
624 
625     _PyErr_ChainStackItem(&fut->fut_cancelled_exc_state);
626 }
627 
628 static int
future_get_result(FutureObj * fut,PyObject ** result)629 future_get_result(FutureObj *fut, PyObject **result)
630 {
631     if (fut->fut_state == STATE_CANCELLED) {
632         future_set_cancelled_error(fut);
633         return -1;
634     }
635 
636     if (fut->fut_state != STATE_FINISHED) {
637         PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
638         return -1;
639     }
640 
641     fut->fut_log_tb = 0;
642     if (fut->fut_exception != NULL) {
643         Py_INCREF(fut->fut_exception);
644         *result = fut->fut_exception;
645         return 1;
646     }
647 
648     Py_INCREF(fut->fut_result);
649     *result = fut->fut_result;
650     return 0;
651 }
652 
653 static PyObject *
future_add_done_callback(FutureObj * fut,PyObject * arg,PyObject * ctx)654 future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
655 {
656     if (!future_is_alive(fut)) {
657         PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
658         return NULL;
659     }
660 
661     if (fut->fut_state != STATE_PENDING) {
662         /* The future is done/cancelled, so schedule the callback
663            right away. */
664         if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
665             return NULL;
666         }
667     }
668     else {
669         /* The future is pending, add a callback.
670 
671            Callbacks in the future object are stored as follows:
672 
673               callback0 -- a pointer to the first callback
674               callbacks -- a list of 2nd, 3rd, ... callbacks
675 
676            Invariants:
677 
678             * callbacks != NULL:
679                 There are some callbacks in in the list.  Just
680                 add the new callback to it.
681 
682             * callbacks == NULL and callback0 == NULL:
683                 This is the first callback.  Set it to callback0.
684 
685             * callbacks == NULL and callback0 != NULL:
686                 This is a second callback.  Initialize callbacks
687                 with a new list and add the new callback to it.
688         */
689 
690         if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
691             Py_INCREF(arg);
692             fut->fut_callback0 = arg;
693             Py_INCREF(ctx);
694             fut->fut_context0 = ctx;
695         }
696         else {
697             PyObject *tup = PyTuple_New(2);
698             if (tup == NULL) {
699                 return NULL;
700             }
701             Py_INCREF(arg);
702             PyTuple_SET_ITEM(tup, 0, arg);
703             Py_INCREF(ctx);
704             PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
705 
706             if (fut->fut_callbacks != NULL) {
707                 int err = PyList_Append(fut->fut_callbacks, tup);
708                 if (err) {
709                     Py_DECREF(tup);
710                     return NULL;
711                 }
712                 Py_DECREF(tup);
713             }
714             else {
715                 fut->fut_callbacks = PyList_New(1);
716                 if (fut->fut_callbacks == NULL) {
717                     return NULL;
718                 }
719 
720                 PyList_SET_ITEM(fut->fut_callbacks, 0, tup);  /* borrow */
721             }
722         }
723     }
724 
725     Py_RETURN_NONE;
726 }
727 
728 static PyObject *
future_cancel(FutureObj * fut,PyObject * msg)729 future_cancel(FutureObj *fut, PyObject *msg)
730 {
731     fut->fut_log_tb = 0;
732 
733     if (fut->fut_state != STATE_PENDING) {
734         Py_RETURN_FALSE;
735     }
736     fut->fut_state = STATE_CANCELLED;
737 
738     Py_XINCREF(msg);
739     Py_XSETREF(fut->fut_cancel_msg, msg);
740 
741     if (future_schedule_callbacks(fut) == -1) {
742         return NULL;
743     }
744 
745     Py_RETURN_TRUE;
746 }
747 
748 /*[clinic input]
749 _asyncio.Future.__init__
750 
751     *
752     loop: object = None
753 
754 This class is *almost* compatible with concurrent.futures.Future.
755 
756     Differences:
757 
758     - result() and exception() do not take a timeout argument and
759       raise an exception when the future isn't done yet.
760 
761     - Callbacks registered with add_done_callback() are always called
762       via the event loop's call_soon_threadsafe().
763 
764     - This class is not compatible with the wait() and as_completed()
765       methods in the concurrent.futures package.
766 [clinic start generated code]*/
767 
768 static int
_asyncio_Future___init___impl(FutureObj * self,PyObject * loop)769 _asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
770 /*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
771 
772 {
773     return future_init(self, loop);
774 }
775 
776 static int
FutureObj_clear(FutureObj * fut)777 FutureObj_clear(FutureObj *fut)
778 {
779     Py_CLEAR(fut->fut_loop);
780     Py_CLEAR(fut->fut_callback0);
781     Py_CLEAR(fut->fut_context0);
782     Py_CLEAR(fut->fut_callbacks);
783     Py_CLEAR(fut->fut_result);
784     Py_CLEAR(fut->fut_exception);
785     Py_CLEAR(fut->fut_source_tb);
786     Py_CLEAR(fut->fut_cancel_msg);
787     _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
788     Py_CLEAR(fut->dict);
789     return 0;
790 }
791 
792 static int
FutureObj_traverse(FutureObj * fut,visitproc visit,void * arg)793 FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
794 {
795     Py_VISIT(fut->fut_loop);
796     Py_VISIT(fut->fut_callback0);
797     Py_VISIT(fut->fut_context0);
798     Py_VISIT(fut->fut_callbacks);
799     Py_VISIT(fut->fut_result);
800     Py_VISIT(fut->fut_exception);
801     Py_VISIT(fut->fut_source_tb);
802     Py_VISIT(fut->fut_cancel_msg);
803     Py_VISIT(fut->dict);
804 
805     _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
806     Py_VISIT(exc_state->exc_type);
807     Py_VISIT(exc_state->exc_value);
808     Py_VISIT(exc_state->exc_traceback);
809 
810     return 0;
811 }
812 
813 /*[clinic input]
814 _asyncio.Future.result
815 
816 Return the result this future represents.
817 
818 If the future has been cancelled, raises CancelledError.  If the
819 future's result isn't yet available, raises InvalidStateError.  If
820 the future is done and has an exception set, this exception is raised.
821 [clinic start generated code]*/
822 
823 static PyObject *
_asyncio_Future_result_impl(FutureObj * self)824 _asyncio_Future_result_impl(FutureObj *self)
825 /*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
826 {
827     PyObject *result;
828 
829     if (!future_is_alive(self)) {
830         PyErr_SetString(asyncio_InvalidStateError,
831                         "Future object is not initialized.");
832         return NULL;
833     }
834 
835     int res = future_get_result(self, &result);
836 
837     if (res == -1) {
838         return NULL;
839     }
840 
841     if (res == 0) {
842         return result;
843     }
844 
845     assert(res == 1);
846 
847     PyErr_SetObject(PyExceptionInstance_Class(result), result);
848     Py_DECREF(result);
849     return NULL;
850 }
851 
852 /*[clinic input]
853 _asyncio.Future.exception
854 
855 Return the exception that was set on this future.
856 
857 The exception (or None if no exception was set) is returned only if
858 the future is done.  If the future has been cancelled, raises
859 CancelledError.  If the future isn't done yet, raises
860 InvalidStateError.
861 [clinic start generated code]*/
862 
863 static PyObject *
_asyncio_Future_exception_impl(FutureObj * self)864 _asyncio_Future_exception_impl(FutureObj *self)
865 /*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
866 {
867     if (!future_is_alive(self)) {
868         PyErr_SetString(asyncio_InvalidStateError,
869                         "Future object is not initialized.");
870         return NULL;
871     }
872 
873     if (self->fut_state == STATE_CANCELLED) {
874         future_set_cancelled_error(self);
875         return NULL;
876     }
877 
878     if (self->fut_state != STATE_FINISHED) {
879         PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
880         return NULL;
881     }
882 
883     if (self->fut_exception != NULL) {
884         self->fut_log_tb = 0;
885         Py_INCREF(self->fut_exception);
886         return self->fut_exception;
887     }
888 
889     Py_RETURN_NONE;
890 }
891 
892 /*[clinic input]
893 _asyncio.Future.set_result
894 
895     result: object
896     /
897 
898 Mark the future done and set its result.
899 
900 If the future is already done when this method is called, raises
901 InvalidStateError.
902 [clinic start generated code]*/
903 
904 static PyObject *
_asyncio_Future_set_result(FutureObj * self,PyObject * result)905 _asyncio_Future_set_result(FutureObj *self, PyObject *result)
906 /*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
907 {
908     ENSURE_FUTURE_ALIVE(self)
909     return future_set_result(self, result);
910 }
911 
912 /*[clinic input]
913 _asyncio.Future.set_exception
914 
915     exception: object
916     /
917 
918 Mark the future done and set an exception.
919 
920 If the future is already done when this method is called, raises
921 InvalidStateError.
922 [clinic start generated code]*/
923 
924 static PyObject *
_asyncio_Future_set_exception(FutureObj * self,PyObject * exception)925 _asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
926 /*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
927 {
928     ENSURE_FUTURE_ALIVE(self)
929     return future_set_exception(self, exception);
930 }
931 
932 /*[clinic input]
933 _asyncio.Future.add_done_callback
934 
935     fn: object
936     /
937     *
938     context: object = NULL
939 
940 Add a callback to be run when the future becomes done.
941 
942 The callback is called with a single argument - the future object. If
943 the future is already done when this is called, the callback is
944 scheduled with call_soon.
945 [clinic start generated code]*/
946 
947 static PyObject *
_asyncio_Future_add_done_callback_impl(FutureObj * self,PyObject * fn,PyObject * context)948 _asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
949                                        PyObject *context)
950 /*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
951 {
952     if (context == NULL) {
953         context = PyContext_CopyCurrent();
954         if (context == NULL) {
955             return NULL;
956         }
957         PyObject *res = future_add_done_callback(self, fn, context);
958         Py_DECREF(context);
959         return res;
960     }
961     return future_add_done_callback(self, fn, context);
962 }
963 
964 /*[clinic input]
965 _asyncio.Future.remove_done_callback
966 
967     fn: object
968     /
969 
970 Remove all instances of a callback from the "call when done" list.
971 
972 Returns the number of callbacks removed.
973 [clinic start generated code]*/
974 
975 static PyObject *
_asyncio_Future_remove_done_callback(FutureObj * self,PyObject * fn)976 _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
977 /*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
978 {
979     PyObject *newlist;
980     Py_ssize_t len, i, j=0;
981     Py_ssize_t cleared_callback0 = 0;
982 
983     ENSURE_FUTURE_ALIVE(self)
984 
985     if (self->fut_callback0 != NULL) {
986         int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ);
987         if (cmp == -1) {
988             return NULL;
989         }
990         if (cmp == 1) {
991             /* callback0 == fn */
992             Py_CLEAR(self->fut_callback0);
993             Py_CLEAR(self->fut_context0);
994             cleared_callback0 = 1;
995         }
996     }
997 
998     if (self->fut_callbacks == NULL) {
999         return PyLong_FromSsize_t(cleared_callback0);
1000     }
1001 
1002     len = PyList_GET_SIZE(self->fut_callbacks);
1003     if (len == 0) {
1004         Py_CLEAR(self->fut_callbacks);
1005         return PyLong_FromSsize_t(cleared_callback0);
1006     }
1007 
1008     if (len == 1) {
1009         PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
1010         int cmp = PyObject_RichCompareBool(
1011             PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ);
1012         if (cmp == -1) {
1013             return NULL;
1014         }
1015         if (cmp == 1) {
1016             /* callbacks[0] == fn */
1017             Py_CLEAR(self->fut_callbacks);
1018             return PyLong_FromSsize_t(1 + cleared_callback0);
1019         }
1020         /* callbacks[0] != fn and len(callbacks) == 1 */
1021         return PyLong_FromSsize_t(cleared_callback0);
1022     }
1023 
1024     newlist = PyList_New(len);
1025     if (newlist == NULL) {
1026         return NULL;
1027     }
1028 
1029     for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
1030         int ret;
1031         PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
1032         Py_INCREF(item);
1033         ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ);
1034         if (ret == 0) {
1035             if (j < len) {
1036                 PyList_SET_ITEM(newlist, j, item);
1037                 j++;
1038                 continue;
1039             }
1040             ret = PyList_Append(newlist, item);
1041         }
1042         Py_DECREF(item);
1043         if (ret < 0) {
1044             goto fail;
1045         }
1046     }
1047 
1048     if (j == 0) {
1049         Py_CLEAR(self->fut_callbacks);
1050         Py_DECREF(newlist);
1051         return PyLong_FromSsize_t(len + cleared_callback0);
1052     }
1053 
1054     if (j < len) {
1055         Py_SET_SIZE(newlist, j);
1056     }
1057     j = PyList_GET_SIZE(newlist);
1058     len = PyList_GET_SIZE(self->fut_callbacks);
1059     if (j != len) {
1060         if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1061             goto fail;
1062         }
1063     }
1064     Py_DECREF(newlist);
1065     return PyLong_FromSsize_t(len - j + cleared_callback0);
1066 
1067 fail:
1068     Py_DECREF(newlist);
1069     return NULL;
1070 }
1071 
1072 /*[clinic input]
1073 _asyncio.Future.cancel
1074 
1075     msg: object = None
1076 
1077 Cancel the future and schedule callbacks.
1078 
1079 If the future is already done or cancelled, return False.  Otherwise,
1080 change the future's state to cancelled, schedule the callbacks and
1081 return True.
1082 [clinic start generated code]*/
1083 
1084 static PyObject *
_asyncio_Future_cancel_impl(FutureObj * self,PyObject * msg)1085 _asyncio_Future_cancel_impl(FutureObj *self, PyObject *msg)
1086 /*[clinic end generated code: output=3edebbc668e5aba3 input=925eb545251f2c5a]*/
1087 {
1088     ENSURE_FUTURE_ALIVE(self)
1089     return future_cancel(self, msg);
1090 }
1091 
1092 /*[clinic input]
1093 _asyncio.Future.cancelled
1094 
1095 Return True if the future was cancelled.
1096 [clinic start generated code]*/
1097 
1098 static PyObject *
_asyncio_Future_cancelled_impl(FutureObj * self)1099 _asyncio_Future_cancelled_impl(FutureObj *self)
1100 /*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
1101 {
1102     if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
1103         Py_RETURN_TRUE;
1104     }
1105     else {
1106         Py_RETURN_FALSE;
1107     }
1108 }
1109 
1110 /*[clinic input]
1111 _asyncio.Future.done
1112 
1113 Return True if the future is done.
1114 
1115 Done means either that a result / exception are available, or that the
1116 future was cancelled.
1117 [clinic start generated code]*/
1118 
1119 static PyObject *
_asyncio_Future_done_impl(FutureObj * self)1120 _asyncio_Future_done_impl(FutureObj *self)
1121 /*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
1122 {
1123     if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
1124         Py_RETURN_FALSE;
1125     }
1126     else {
1127         Py_RETURN_TRUE;
1128     }
1129 }
1130 
1131 /*[clinic input]
1132 _asyncio.Future.get_loop
1133 
1134 Return the event loop the Future is bound to.
1135 [clinic start generated code]*/
1136 
1137 static PyObject *
_asyncio_Future_get_loop_impl(FutureObj * self)1138 _asyncio_Future_get_loop_impl(FutureObj *self)
1139 /*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1140 {
1141     ENSURE_FUTURE_ALIVE(self)
1142     Py_INCREF(self->fut_loop);
1143     return self->fut_loop;
1144 }
1145 
1146 static PyObject *
FutureObj_get_blocking(FutureObj * fut,void * Py_UNUSED (ignored))1147 FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
1148 {
1149     if (future_is_alive(fut) && fut->fut_blocking) {
1150         Py_RETURN_TRUE;
1151     }
1152     else {
1153         Py_RETURN_FALSE;
1154     }
1155 }
1156 
1157 static int
FutureObj_set_blocking(FutureObj * fut,PyObject * val,void * Py_UNUSED (ignored))1158 FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
1159 {
1160     if (future_ensure_alive(fut)) {
1161         return -1;
1162     }
1163     if (val == NULL) {
1164         PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1165         return -1;
1166     }
1167 
1168     int is_true = PyObject_IsTrue(val);
1169     if (is_true < 0) {
1170         return -1;
1171     }
1172     fut->fut_blocking = is_true;
1173     return 0;
1174 }
1175 
1176 static PyObject *
FutureObj_get_log_traceback(FutureObj * fut,void * Py_UNUSED (ignored))1177 FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
1178 {
1179     ENSURE_FUTURE_ALIVE(fut)
1180     if (fut->fut_log_tb) {
1181         Py_RETURN_TRUE;
1182     }
1183     else {
1184         Py_RETURN_FALSE;
1185     }
1186 }
1187 
1188 static int
FutureObj_set_log_traceback(FutureObj * fut,PyObject * val,void * Py_UNUSED (ignored))1189 FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
1190 {
1191     if (val == NULL) {
1192         PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1193         return -1;
1194     }
1195     int is_true = PyObject_IsTrue(val);
1196     if (is_true < 0) {
1197         return -1;
1198     }
1199     if (is_true) {
1200         PyErr_SetString(PyExc_ValueError,
1201                         "_log_traceback can only be set to False");
1202         return -1;
1203     }
1204     fut->fut_log_tb = is_true;
1205     return 0;
1206 }
1207 
1208 static PyObject *
FutureObj_get_loop(FutureObj * fut,void * Py_UNUSED (ignored))1209 FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
1210 {
1211     if (!future_is_alive(fut)) {
1212         Py_RETURN_NONE;
1213     }
1214     Py_INCREF(fut->fut_loop);
1215     return fut->fut_loop;
1216 }
1217 
1218 static PyObject *
FutureObj_get_callbacks(FutureObj * fut,void * Py_UNUSED (ignored))1219 FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
1220 {
1221     Py_ssize_t i;
1222 
1223     ENSURE_FUTURE_ALIVE(fut)
1224 
1225     if (fut->fut_callback0 == NULL) {
1226         if (fut->fut_callbacks == NULL) {
1227             Py_RETURN_NONE;
1228         }
1229 
1230         Py_INCREF(fut->fut_callbacks);
1231         return fut->fut_callbacks;
1232     }
1233 
1234     Py_ssize_t len = 1;
1235     if (fut->fut_callbacks != NULL) {
1236         len += PyList_GET_SIZE(fut->fut_callbacks);
1237     }
1238 
1239 
1240     PyObject *new_list = PyList_New(len);
1241     if (new_list == NULL) {
1242         return NULL;
1243     }
1244 
1245     PyObject *tup0 = PyTuple_New(2);
1246     if (tup0 == NULL) {
1247         Py_DECREF(new_list);
1248         return NULL;
1249     }
1250 
1251     Py_INCREF(fut->fut_callback0);
1252     PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1253     assert(fut->fut_context0 != NULL);
1254     Py_INCREF(fut->fut_context0);
1255     PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1256 
1257     PyList_SET_ITEM(new_list, 0, tup0);
1258 
1259     if (fut->fut_callbacks != NULL) {
1260         for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1261             PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1262             Py_INCREF(cb);
1263             PyList_SET_ITEM(new_list, i + 1, cb);
1264         }
1265     }
1266 
1267     return new_list;
1268 }
1269 
1270 static PyObject *
FutureObj_get_result(FutureObj * fut,void * Py_UNUSED (ignored))1271 FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
1272 {
1273     ENSURE_FUTURE_ALIVE(fut)
1274     if (fut->fut_result == NULL) {
1275         Py_RETURN_NONE;
1276     }
1277     Py_INCREF(fut->fut_result);
1278     return fut->fut_result;
1279 }
1280 
1281 static PyObject *
FutureObj_get_exception(FutureObj * fut,void * Py_UNUSED (ignored))1282 FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
1283 {
1284     ENSURE_FUTURE_ALIVE(fut)
1285     if (fut->fut_exception == NULL) {
1286         Py_RETURN_NONE;
1287     }
1288     Py_INCREF(fut->fut_exception);
1289     return fut->fut_exception;
1290 }
1291 
1292 static PyObject *
FutureObj_get_source_traceback(FutureObj * fut,void * Py_UNUSED (ignored))1293 FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
1294 {
1295     if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
1296         Py_RETURN_NONE;
1297     }
1298     Py_INCREF(fut->fut_source_tb);
1299     return fut->fut_source_tb;
1300 }
1301 
1302 static PyObject *
FutureObj_get_cancel_message(FutureObj * fut,void * Py_UNUSED (ignored))1303 FutureObj_get_cancel_message(FutureObj *fut, void *Py_UNUSED(ignored))
1304 {
1305     if (fut->fut_cancel_msg == NULL) {
1306         Py_RETURN_NONE;
1307     }
1308     Py_INCREF(fut->fut_cancel_msg);
1309     return fut->fut_cancel_msg;
1310 }
1311 
1312 static int
FutureObj_set_cancel_message(FutureObj * fut,PyObject * msg,void * Py_UNUSED (ignored))1313 FutureObj_set_cancel_message(FutureObj *fut, PyObject *msg,
1314                              void *Py_UNUSED(ignored))
1315 {
1316     if (msg == NULL) {
1317         PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1318         return -1;
1319     }
1320     Py_INCREF(msg);
1321     Py_XSETREF(fut->fut_cancel_msg, msg);
1322     return 0;
1323 }
1324 
1325 static PyObject *
FutureObj_get_state(FutureObj * fut,void * Py_UNUSED (ignored))1326 FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
1327 {
1328     _Py_IDENTIFIER(PENDING);
1329     _Py_IDENTIFIER(CANCELLED);
1330     _Py_IDENTIFIER(FINISHED);
1331     PyObject *ret = NULL;
1332 
1333     ENSURE_FUTURE_ALIVE(fut)
1334 
1335     switch (fut->fut_state) {
1336     case STATE_PENDING:
1337         ret = _PyUnicode_FromId(&PyId_PENDING);
1338         break;
1339     case STATE_CANCELLED:
1340         ret = _PyUnicode_FromId(&PyId_CANCELLED);
1341         break;
1342     case STATE_FINISHED:
1343         ret = _PyUnicode_FromId(&PyId_FINISHED);
1344         break;
1345     default:
1346         assert (0);
1347     }
1348     Py_XINCREF(ret);
1349     return ret;
1350 }
1351 
1352 /*[clinic input]
1353 _asyncio.Future._make_cancelled_error
1354 
1355 Create the CancelledError to raise if the Future is cancelled.
1356 
1357 This should only be called once when handling a cancellation since
1358 it erases the context exception value.
1359 [clinic start generated code]*/
1360 
1361 static PyObject *
_asyncio_Future__make_cancelled_error_impl(FutureObj * self)1362 _asyncio_Future__make_cancelled_error_impl(FutureObj *self)
1363 /*[clinic end generated code: output=a5df276f6c1213de input=ac6effe4ba795ecc]*/
1364 {
1365     PyObject *exc = create_cancelled_error(self->fut_cancel_msg);
1366     _PyErr_StackItem *exc_state = &self->fut_cancelled_exc_state;
1367     /* Transfer ownership of exc_value from exc_state to exc since we are
1368        done with it. */
1369     PyException_SetContext(exc, exc_state->exc_value);
1370     exc_state->exc_value = NULL;
1371 
1372     return exc;
1373 }
1374 
1375 /*[clinic input]
1376 _asyncio.Future._repr_info
1377 [clinic start generated code]*/
1378 
1379 static PyObject *
_asyncio_Future__repr_info_impl(FutureObj * self)1380 _asyncio_Future__repr_info_impl(FutureObj *self)
1381 /*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
1382 {
1383     return PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
1384 }
1385 
1386 static PyObject *
FutureObj_repr(FutureObj * fut)1387 FutureObj_repr(FutureObj *fut)
1388 {
1389     _Py_IDENTIFIER(_repr_info);
1390 
1391     ENSURE_FUTURE_ALIVE(fut)
1392 
1393     PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
1394                                                    &PyId__repr_info);
1395     if (rinfo == NULL) {
1396         return NULL;
1397     }
1398 
1399     PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
1400     Py_DECREF(rinfo);
1401     if (rinfo_s == NULL) {
1402         return NULL;
1403     }
1404 
1405     PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1406                                           _PyType_Name(Py_TYPE(fut)), rinfo_s);
1407     Py_DECREF(rinfo_s);
1408     return rstr;
1409 }
1410 
1411 static void
FutureObj_finalize(FutureObj * fut)1412 FutureObj_finalize(FutureObj *fut)
1413 {
1414     _Py_IDENTIFIER(call_exception_handler);
1415     _Py_IDENTIFIER(message);
1416     _Py_IDENTIFIER(exception);
1417     _Py_IDENTIFIER(future);
1418     _Py_IDENTIFIER(source_traceback);
1419 
1420     PyObject *error_type, *error_value, *error_traceback;
1421     PyObject *context;
1422     PyObject *message = NULL;
1423     PyObject *func;
1424 
1425     if (!fut->fut_log_tb) {
1426         return;
1427     }
1428     assert(fut->fut_exception != NULL);
1429     fut->fut_log_tb = 0;
1430 
1431     /* Save the current exception, if any. */
1432     PyErr_Fetch(&error_type, &error_value, &error_traceback);
1433 
1434     context = PyDict_New();
1435     if (context == NULL) {
1436         goto finally;
1437     }
1438 
1439     message = PyUnicode_FromFormat(
1440         "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
1441     if (message == NULL) {
1442         goto finally;
1443     }
1444 
1445     if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1446         _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1447         _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1448         goto finally;
1449     }
1450     if (fut->fut_source_tb != NULL) {
1451         if (_PyDict_SetItemId(context, &PyId_source_traceback,
1452                               fut->fut_source_tb) < 0) {
1453             goto finally;
1454         }
1455     }
1456 
1457     func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1458     if (func != NULL) {
1459         PyObject *res = PyObject_CallOneArg(func, context);
1460         if (res == NULL) {
1461             PyErr_WriteUnraisable(func);
1462         }
1463         else {
1464             Py_DECREF(res);
1465         }
1466         Py_DECREF(func);
1467     }
1468 
1469 finally:
1470     Py_XDECREF(context);
1471     Py_XDECREF(message);
1472 
1473     /* Restore the saved exception. */
1474     PyErr_Restore(error_type, error_value, error_traceback);
1475 }
1476 
1477 static PyObject *
future_cls_getitem(PyObject * cls,PyObject * type)1478 future_cls_getitem(PyObject *cls, PyObject *type)
1479 {
1480     Py_INCREF(cls);
1481     return cls;
1482 }
1483 
1484 static PyAsyncMethods FutureType_as_async = {
1485     (unaryfunc)future_new_iter,         /* am_await */
1486     0,                                  /* am_aiter */
1487     0                                   /* am_anext */
1488 };
1489 
1490 static PyMethodDef FutureType_methods[] = {
1491     _ASYNCIO_FUTURE_RESULT_METHODDEF
1492     _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1493     _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1494     _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1495     _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1496     _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1497     _ASYNCIO_FUTURE_CANCEL_METHODDEF
1498     _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1499     _ASYNCIO_FUTURE_DONE_METHODDEF
1500     _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
1501     _ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF
1502     _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
1503     {"__class_getitem__", future_cls_getitem, METH_O|METH_CLASS, NULL},
1504     {NULL, NULL}        /* Sentinel */
1505 };
1506 
1507 #define FUTURE_COMMON_GETSETLIST                                              \
1508     {"_state", (getter)FutureObj_get_state, NULL, NULL},                      \
1509     {"_asyncio_future_blocking", (getter)FutureObj_get_blocking,              \
1510                                  (setter)FutureObj_set_blocking, NULL},       \
1511     {"_loop", (getter)FutureObj_get_loop, NULL, NULL},                        \
1512     {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL},              \
1513     {"_result", (getter)FutureObj_get_result, NULL, NULL},                    \
1514     {"_exception", (getter)FutureObj_get_exception, NULL, NULL},              \
1515     {"_log_traceback", (getter)FutureObj_get_log_traceback,                   \
1516                        (setter)FutureObj_set_log_traceback, NULL},            \
1517     {"_source_traceback", (getter)FutureObj_get_source_traceback,             \
1518                           NULL, NULL},                                        \
1519     {"_cancel_message", (getter)FutureObj_get_cancel_message,                 \
1520                         (setter)FutureObj_set_cancel_message, NULL},
1521 
1522 static PyGetSetDef FutureType_getsetlist[] = {
1523     FUTURE_COMMON_GETSETLIST
1524     {NULL} /* Sentinel */
1525 };
1526 
1527 static void FutureObj_dealloc(PyObject *self);
1528 
1529 static PyTypeObject FutureType = {
1530     PyVarObject_HEAD_INIT(NULL, 0)
1531     "_asyncio.Future",
1532     sizeof(FutureObj),                       /* tp_basicsize */
1533     .tp_dealloc = FutureObj_dealloc,
1534     .tp_as_async = &FutureType_as_async,
1535     .tp_repr = (reprfunc)FutureObj_repr,
1536     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
1537     .tp_doc = _asyncio_Future___init____doc__,
1538     .tp_traverse = (traverseproc)FutureObj_traverse,
1539     .tp_clear = (inquiry)FutureObj_clear,
1540     .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
1541     .tp_iter = (getiterfunc)future_new_iter,
1542     .tp_methods = FutureType_methods,
1543     .tp_getset = FutureType_getsetlist,
1544     .tp_dictoffset = offsetof(FutureObj, dict),
1545     .tp_init = (initproc)_asyncio_Future___init__,
1546     .tp_new = PyType_GenericNew,
1547     .tp_finalize = (destructor)FutureObj_finalize,
1548 };
1549 
1550 static void
FutureObj_dealloc(PyObject * self)1551 FutureObj_dealloc(PyObject *self)
1552 {
1553     FutureObj *fut = (FutureObj *)self;
1554 
1555     if (Future_CheckExact(fut)) {
1556         /* When fut is subclass of Future, finalizer is called from
1557          * subtype_dealloc.
1558          */
1559         if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1560             // resurrected.
1561             return;
1562         }
1563     }
1564 
1565     PyObject_GC_UnTrack(self);
1566 
1567     if (fut->fut_weakreflist != NULL) {
1568         PyObject_ClearWeakRefs(self);
1569     }
1570 
1571     (void)FutureObj_clear(fut);
1572     Py_TYPE(fut)->tp_free(fut);
1573 }
1574 
1575 
1576 /*********************** Future Iterator **************************/
1577 
1578 typedef struct {
1579     PyObject_HEAD
1580     FutureObj *future;
1581 } futureiterobject;
1582 
1583 
1584 #define FI_FREELIST_MAXLEN 255
1585 static futureiterobject *fi_freelist = NULL;
1586 static Py_ssize_t fi_freelist_len = 0;
1587 
1588 
1589 static void
FutureIter_dealloc(futureiterobject * it)1590 FutureIter_dealloc(futureiterobject *it)
1591 {
1592     PyObject_GC_UnTrack(it);
1593     Py_CLEAR(it->future);
1594 
1595     if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1596         fi_freelist_len++;
1597         it->future = (FutureObj*) fi_freelist;
1598         fi_freelist = it;
1599     }
1600     else {
1601         PyObject_GC_Del(it);
1602     }
1603 }
1604 
1605 static PyObject *
FutureIter_iternext(futureiterobject * it)1606 FutureIter_iternext(futureiterobject *it)
1607 {
1608     PyObject *res;
1609     FutureObj *fut = it->future;
1610 
1611     if (fut == NULL) {
1612         return NULL;
1613     }
1614 
1615     if (fut->fut_state == STATE_PENDING) {
1616         if (!fut->fut_blocking) {
1617             fut->fut_blocking = 1;
1618             Py_INCREF(fut);
1619             return (PyObject *)fut;
1620         }
1621         PyErr_SetString(PyExc_RuntimeError,
1622                         "await wasn't used with future");
1623         return NULL;
1624     }
1625 
1626     it->future = NULL;
1627     res = _asyncio_Future_result_impl(fut);
1628     if (res != NULL) {
1629         /* The result of the Future is not an exception. */
1630         (void)_PyGen_SetStopIterationValue(res);
1631         Py_DECREF(res);
1632     }
1633 
1634     Py_DECREF(fut);
1635     return NULL;
1636 }
1637 
1638 static PyObject *
FutureIter_send(futureiterobject * self,PyObject * unused)1639 FutureIter_send(futureiterobject *self, PyObject *unused)
1640 {
1641     /* Future.__iter__ doesn't care about values that are pushed to the
1642      * generator, it just returns self.result().
1643      */
1644     return FutureIter_iternext(self);
1645 }
1646 
1647 static PyObject *
FutureIter_throw(futureiterobject * self,PyObject * args)1648 FutureIter_throw(futureiterobject *self, PyObject *args)
1649 {
1650     PyObject *type, *val = NULL, *tb = NULL;
1651     if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1652         return NULL;
1653 
1654     if (val == Py_None) {
1655         val = NULL;
1656     }
1657     if (tb == Py_None) {
1658         tb = NULL;
1659     } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1660         PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1661         return NULL;
1662     }
1663 
1664     Py_INCREF(type);
1665     Py_XINCREF(val);
1666     Py_XINCREF(tb);
1667 
1668     if (PyExceptionClass_Check(type)) {
1669         PyErr_NormalizeException(&type, &val, &tb);
1670         /* No need to call PyException_SetTraceback since we'll be calling
1671            PyErr_Restore for `type`, `val`, and `tb`. */
1672     } else if (PyExceptionInstance_Check(type)) {
1673         if (val) {
1674             PyErr_SetString(PyExc_TypeError,
1675                             "instance exception may not have a separate value");
1676             goto fail;
1677         }
1678         val = type;
1679         type = PyExceptionInstance_Class(type);
1680         Py_INCREF(type);
1681         if (tb == NULL)
1682             tb = PyException_GetTraceback(val);
1683     } else {
1684         PyErr_SetString(PyExc_TypeError,
1685                         "exceptions must be classes deriving BaseException or "
1686                         "instances of such a class");
1687         goto fail;
1688     }
1689 
1690     Py_CLEAR(self->future);
1691 
1692     PyErr_Restore(type, val, tb);
1693 
1694     return NULL;
1695 
1696   fail:
1697     Py_DECREF(type);
1698     Py_XDECREF(val);
1699     Py_XDECREF(tb);
1700     return NULL;
1701 }
1702 
1703 static PyObject *
FutureIter_close(futureiterobject * self,PyObject * arg)1704 FutureIter_close(futureiterobject *self, PyObject *arg)
1705 {
1706     Py_CLEAR(self->future);
1707     Py_RETURN_NONE;
1708 }
1709 
1710 static int
FutureIter_traverse(futureiterobject * it,visitproc visit,void * arg)1711 FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1712 {
1713     Py_VISIT(it->future);
1714     return 0;
1715 }
1716 
1717 static PyMethodDef FutureIter_methods[] = {
1718     {"send",  (PyCFunction)FutureIter_send, METH_O, NULL},
1719     {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1720     {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1721     {NULL, NULL}        /* Sentinel */
1722 };
1723 
1724 static PyTypeObject FutureIterType = {
1725     PyVarObject_HEAD_INIT(NULL, 0)
1726     "_asyncio.FutureIter",
1727     .tp_basicsize = sizeof(futureiterobject),
1728     .tp_itemsize = 0,
1729     .tp_dealloc = (destructor)FutureIter_dealloc,
1730     .tp_getattro = PyObject_GenericGetAttr,
1731     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1732     .tp_traverse = (traverseproc)FutureIter_traverse,
1733     .tp_iter = PyObject_SelfIter,
1734     .tp_iternext = (iternextfunc)FutureIter_iternext,
1735     .tp_methods = FutureIter_methods,
1736 };
1737 
1738 static PyObject *
future_new_iter(PyObject * fut)1739 future_new_iter(PyObject *fut)
1740 {
1741     futureiterobject *it;
1742 
1743     if (!PyObject_TypeCheck(fut, &FutureType)) {
1744         PyErr_BadInternalCall();
1745         return NULL;
1746     }
1747 
1748     ENSURE_FUTURE_ALIVE(fut)
1749 
1750     if (fi_freelist_len) {
1751         fi_freelist_len--;
1752         it = fi_freelist;
1753         fi_freelist = (futureiterobject*) it->future;
1754         it->future = NULL;
1755         _Py_NewReference((PyObject*) it);
1756     }
1757     else {
1758         it = PyObject_GC_New(futureiterobject, &FutureIterType);
1759         if (it == NULL) {
1760             return NULL;
1761         }
1762     }
1763 
1764     Py_INCREF(fut);
1765     it->future = (FutureObj*)fut;
1766     PyObject_GC_Track(it);
1767     return (PyObject*)it;
1768 }
1769 
1770 
1771 /*********************** Task **************************/
1772 
1773 
1774 /*[clinic input]
1775 class _asyncio.Task "TaskObj *" "&Task_Type"
1776 [clinic start generated code]*/
1777 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1778 
1779 static int task_call_step_soon(TaskObj *, PyObject *);
1780 static PyObject * task_wakeup(TaskObj *, PyObject *);
1781 static PyObject * task_step(TaskObj *, PyObject *);
1782 
1783 /* ----- Task._step wrapper */
1784 
1785 static int
TaskStepMethWrapper_clear(TaskStepMethWrapper * o)1786 TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
1787 {
1788     Py_CLEAR(o->sw_task);
1789     Py_CLEAR(o->sw_arg);
1790     return 0;
1791 }
1792 
1793 static void
TaskStepMethWrapper_dealloc(TaskStepMethWrapper * o)1794 TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
1795 {
1796     PyObject_GC_UnTrack(o);
1797     (void)TaskStepMethWrapper_clear(o);
1798     Py_TYPE(o)->tp_free(o);
1799 }
1800 
1801 static PyObject *
TaskStepMethWrapper_call(TaskStepMethWrapper * o,PyObject * args,PyObject * kwds)1802 TaskStepMethWrapper_call(TaskStepMethWrapper *o,
1803                          PyObject *args, PyObject *kwds)
1804 {
1805     if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1806         PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1807         return NULL;
1808     }
1809     if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1810         PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1811         return NULL;
1812     }
1813     return task_step(o->sw_task, o->sw_arg);
1814 }
1815 
1816 static int
TaskStepMethWrapper_traverse(TaskStepMethWrapper * o,visitproc visit,void * arg)1817 TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
1818                              visitproc visit, void *arg)
1819 {
1820     Py_VISIT(o->sw_task);
1821     Py_VISIT(o->sw_arg);
1822     return 0;
1823 }
1824 
1825 static PyObject *
TaskStepMethWrapper_get___self__(TaskStepMethWrapper * o,void * Py_UNUSED (ignored))1826 TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
1827 {
1828     if (o->sw_task) {
1829         Py_INCREF(o->sw_task);
1830         return (PyObject*)o->sw_task;
1831     }
1832     Py_RETURN_NONE;
1833 }
1834 
1835 static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1836     {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
1837     {NULL} /* Sentinel */
1838 };
1839 
1840 static PyTypeObject TaskStepMethWrapper_Type = {
1841     PyVarObject_HEAD_INIT(NULL, 0)
1842     "TaskStepMethWrapper",
1843     .tp_basicsize = sizeof(TaskStepMethWrapper),
1844     .tp_itemsize = 0,
1845     .tp_getset = TaskStepMethWrapper_getsetlist,
1846     .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1847     .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
1848     .tp_getattro = PyObject_GenericGetAttr,
1849     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1850     .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1851     .tp_clear = (inquiry)TaskStepMethWrapper_clear,
1852 };
1853 
1854 static PyObject *
TaskStepMethWrapper_new(TaskObj * task,PyObject * arg)1855 TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
1856 {
1857     TaskStepMethWrapper *o;
1858     o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
1859     if (o == NULL) {
1860         return NULL;
1861     }
1862 
1863     Py_INCREF(task);
1864     o->sw_task = task;
1865 
1866     Py_XINCREF(arg);
1867     o->sw_arg = arg;
1868 
1869     PyObject_GC_Track(o);
1870     return (PyObject*) o;
1871 }
1872 
1873 /* ----- Task._wakeup wrapper */
1874 
1875 static PyObject *
TaskWakeupMethWrapper_call(TaskWakeupMethWrapper * o,PyObject * args,PyObject * kwds)1876 TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1877                            PyObject *args, PyObject *kwds)
1878 {
1879     PyObject *fut;
1880 
1881     if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1882         PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1883         return NULL;
1884     }
1885     if (!PyArg_ParseTuple(args, "O", &fut)) {
1886         return NULL;
1887     }
1888 
1889     return task_wakeup(o->ww_task, fut);
1890 }
1891 
1892 static int
TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper * o)1893 TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1894 {
1895     Py_CLEAR(o->ww_task);
1896     return 0;
1897 }
1898 
1899 static int
TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper * o,visitproc visit,void * arg)1900 TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1901                                visitproc visit, void *arg)
1902 {
1903     Py_VISIT(o->ww_task);
1904     return 0;
1905 }
1906 
1907 static void
TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper * o)1908 TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1909 {
1910     PyObject_GC_UnTrack(o);
1911     (void)TaskWakeupMethWrapper_clear(o);
1912     Py_TYPE(o)->tp_free(o);
1913 }
1914 
1915 static PyObject *
TaskWakeupMethWrapper_get___self__(TaskWakeupMethWrapper * o,void * Py_UNUSED (ignored))1916 TaskWakeupMethWrapper_get___self__(TaskWakeupMethWrapper *o, void *Py_UNUSED(ignored))
1917 {
1918     if (o->ww_task) {
1919         Py_INCREF(o->ww_task);
1920         return (PyObject*)o->ww_task;
1921     }
1922     Py_RETURN_NONE;
1923 }
1924 
1925 static PyGetSetDef TaskWakeupMethWrapper_getsetlist[] = {
1926     {"__self__", (getter)TaskWakeupMethWrapper_get___self__, NULL, NULL},
1927     {NULL} /* Sentinel */
1928 };
1929 
1930 static PyTypeObject TaskWakeupMethWrapper_Type = {
1931     PyVarObject_HEAD_INIT(NULL, 0)
1932     "TaskWakeupMethWrapper",
1933     .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1934     .tp_itemsize = 0,
1935     .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1936     .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1937     .tp_getattro = PyObject_GenericGetAttr,
1938     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1939     .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1940     .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1941     .tp_getset = TaskWakeupMethWrapper_getsetlist,
1942 };
1943 
1944 static PyObject *
TaskWakeupMethWrapper_new(TaskObj * task)1945 TaskWakeupMethWrapper_new(TaskObj *task)
1946 {
1947     TaskWakeupMethWrapper *o;
1948     o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1949     if (o == NULL) {
1950         return NULL;
1951     }
1952 
1953     Py_INCREF(task);
1954     o->ww_task = task;
1955 
1956     PyObject_GC_Track(o);
1957     return (PyObject*) o;
1958 }
1959 
1960 /* ----- Task introspection helpers */
1961 
1962 static int
register_task(PyObject * task)1963 register_task(PyObject *task)
1964 {
1965     _Py_IDENTIFIER(add);
1966 
1967     PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1968                                                  &PyId_add, task);
1969     if (res == NULL) {
1970         return -1;
1971     }
1972     Py_DECREF(res);
1973     return 0;
1974 }
1975 
1976 
1977 static int
unregister_task(PyObject * task)1978 unregister_task(PyObject *task)
1979 {
1980     _Py_IDENTIFIER(discard);
1981 
1982     PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1983                                                  &PyId_discard, task);
1984     if (res == NULL) {
1985         return -1;
1986     }
1987     Py_DECREF(res);
1988     return 0;
1989 }
1990 
1991 
1992 static int
enter_task(PyObject * loop,PyObject * task)1993 enter_task(PyObject *loop, PyObject *task)
1994 {
1995     PyObject *item;
1996     Py_hash_t hash;
1997     hash = PyObject_Hash(loop);
1998     if (hash == -1) {
1999         return -1;
2000     }
2001     item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
2002     if (item != NULL) {
2003         Py_INCREF(item);
2004         PyErr_Format(
2005             PyExc_RuntimeError,
2006             "Cannot enter into task %R while another " \
2007             "task %R is being executed.",
2008             task, item, NULL);
2009         Py_DECREF(item);
2010         return -1;
2011     }
2012     if (PyErr_Occurred()) {
2013         return -1;
2014     }
2015     return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
2016 }
2017 
2018 
2019 static int
leave_task(PyObject * loop,PyObject * task)2020 leave_task(PyObject *loop, PyObject *task)
2021 /*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
2022 {
2023     PyObject *item;
2024     Py_hash_t hash;
2025     hash = PyObject_Hash(loop);
2026     if (hash == -1) {
2027         return -1;
2028     }
2029     item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
2030     if (item != task) {
2031         if (item == NULL) {
2032             /* Not entered, replace with None */
2033             item = Py_None;
2034         }
2035         PyErr_Format(
2036             PyExc_RuntimeError,
2037             "Leaving task %R does not match the current task %R.",
2038             task, item, NULL);
2039         return -1;
2040     }
2041     return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
2042 }
2043 
2044 /* ----- Task */
2045 
2046 /*[clinic input]
2047 _asyncio.Task.__init__
2048 
2049     coro: object
2050     *
2051     loop: object = None
2052     name: object = None
2053 
2054 A coroutine wrapped in a Future.
2055 [clinic start generated code]*/
2056 
2057 static int
_asyncio_Task___init___impl(TaskObj * self,PyObject * coro,PyObject * loop,PyObject * name)2058 _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2059                             PyObject *name)
2060 /*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
2061 {
2062     if (future_init((FutureObj*)self, loop)) {
2063         return -1;
2064     }
2065 
2066     int is_coro = is_coroutine(coro);
2067     if (is_coro == -1) {
2068         return -1;
2069     }
2070     if (is_coro == 0) {
2071         self->task_log_destroy_pending = 0;
2072         PyErr_Format(PyExc_TypeError,
2073                      "a coroutine was expected, got %R",
2074                      coro, NULL);
2075         return -1;
2076     }
2077 
2078     Py_XSETREF(self->task_context, PyContext_CopyCurrent());
2079     if (self->task_context == NULL) {
2080         return -1;
2081     }
2082 
2083     Py_CLEAR(self->task_fut_waiter);
2084     self->task_must_cancel = 0;
2085     self->task_log_destroy_pending = 1;
2086     Py_INCREF(coro);
2087     Py_XSETREF(self->task_coro, coro);
2088 
2089     if (name == Py_None) {
2090         name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
2091     } else if (!PyUnicode_CheckExact(name)) {
2092         name = PyObject_Str(name);
2093     } else {
2094         Py_INCREF(name);
2095     }
2096     Py_XSETREF(self->task_name, name);
2097     if (self->task_name == NULL) {
2098         return -1;
2099     }
2100 
2101     if (task_call_step_soon(self, NULL)) {
2102         return -1;
2103     }
2104     return register_task((PyObject*)self);
2105 }
2106 
2107 static int
TaskObj_clear(TaskObj * task)2108 TaskObj_clear(TaskObj *task)
2109 {
2110     (void)FutureObj_clear((FutureObj*) task);
2111     Py_CLEAR(task->task_context);
2112     Py_CLEAR(task->task_coro);
2113     Py_CLEAR(task->task_name);
2114     Py_CLEAR(task->task_fut_waiter);
2115     return 0;
2116 }
2117 
2118 static int
TaskObj_traverse(TaskObj * task,visitproc visit,void * arg)2119 TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2120 {
2121     Py_VISIT(task->task_context);
2122     Py_VISIT(task->task_coro);
2123     Py_VISIT(task->task_name);
2124     Py_VISIT(task->task_fut_waiter);
2125     (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2126     return 0;
2127 }
2128 
2129 static PyObject *
TaskObj_get_log_destroy_pending(TaskObj * task,void * Py_UNUSED (ignored))2130 TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
2131 {
2132     if (task->task_log_destroy_pending) {
2133         Py_RETURN_TRUE;
2134     }
2135     else {
2136         Py_RETURN_FALSE;
2137     }
2138 }
2139 
2140 static int
TaskObj_set_log_destroy_pending(TaskObj * task,PyObject * val,void * Py_UNUSED (ignored))2141 TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
2142 {
2143     if (val == NULL) {
2144         PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2145         return -1;
2146     }
2147     int is_true = PyObject_IsTrue(val);
2148     if (is_true < 0) {
2149         return -1;
2150     }
2151     task->task_log_destroy_pending = is_true;
2152     return 0;
2153 }
2154 
2155 static PyObject *
TaskObj_get_must_cancel(TaskObj * task,void * Py_UNUSED (ignored))2156 TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
2157 {
2158     if (task->task_must_cancel) {
2159         Py_RETURN_TRUE;
2160     }
2161     else {
2162         Py_RETURN_FALSE;
2163     }
2164 }
2165 
2166 static PyObject *
TaskObj_get_coro(TaskObj * task,void * Py_UNUSED (ignored))2167 TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
2168 {
2169     if (task->task_coro) {
2170         Py_INCREF(task->task_coro);
2171         return task->task_coro;
2172     }
2173 
2174     Py_RETURN_NONE;
2175 }
2176 
2177 static PyObject *
TaskObj_get_fut_waiter(TaskObj * task,void * Py_UNUSED (ignored))2178 TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
2179 {
2180     if (task->task_fut_waiter) {
2181         Py_INCREF(task->task_fut_waiter);
2182         return task->task_fut_waiter;
2183     }
2184 
2185     Py_RETURN_NONE;
2186 }
2187 
2188 /*[clinic input]
2189 _asyncio.Task._make_cancelled_error
2190 
2191 Create the CancelledError to raise if the Task is cancelled.
2192 
2193 This should only be called once when handling a cancellation since
2194 it erases the context exception value.
2195 [clinic start generated code]*/
2196 
2197 static PyObject *
_asyncio_Task__make_cancelled_error_impl(TaskObj * self)2198 _asyncio_Task__make_cancelled_error_impl(TaskObj *self)
2199 /*[clinic end generated code: output=55a819e8b4276fab input=52c0e32de8e2f840]*/
2200 {
2201     FutureObj *fut = (FutureObj*)self;
2202     return _asyncio_Future__make_cancelled_error_impl(fut);
2203 }
2204 
2205 
2206 /*[clinic input]
2207 _asyncio.Task._repr_info
2208 [clinic start generated code]*/
2209 
2210 static PyObject *
_asyncio_Task__repr_info_impl(TaskObj * self)2211 _asyncio_Task__repr_info_impl(TaskObj *self)
2212 /*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2213 {
2214     return PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
2215 }
2216 
2217 /*[clinic input]
2218 _asyncio.Task.cancel
2219 
2220     msg: object = None
2221 
2222 Request that this task cancel itself.
2223 
2224 This arranges for a CancelledError to be thrown into the
2225 wrapped coroutine on the next cycle through the event loop.
2226 The coroutine then has a chance to clean up or even deny
2227 the request using try/except/finally.
2228 
2229 Unlike Future.cancel, this does not guarantee that the
2230 task will be cancelled: the exception might be caught and
2231 acted upon, delaying cancellation of the task or preventing
2232 cancellation completely.  The task may also return a value or
2233 raise a different exception.
2234 
2235 Immediately after this method is called, Task.cancelled() will
2236 not return True (unless the task was already cancelled).  A
2237 task will be marked as cancelled when the wrapped coroutine
2238 terminates with a CancelledError exception (even if cancel()
2239 was not called).
2240 [clinic start generated code]*/
2241 
2242 static PyObject *
_asyncio_Task_cancel_impl(TaskObj * self,PyObject * msg)2243 _asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
2244 /*[clinic end generated code: output=c66b60d41c74f9f1 input=f4ff8e8ffc5f1c00]*/
2245 {
2246     self->task_log_tb = 0;
2247 
2248     if (self->task_state != STATE_PENDING) {
2249         Py_RETURN_FALSE;
2250     }
2251 
2252     if (self->task_fut_waiter) {
2253         PyObject *res;
2254         int is_true;
2255 
2256         res = _PyObject_CallMethodIdOneArg(self->task_fut_waiter,
2257                                            &PyId_cancel, msg);
2258         if (res == NULL) {
2259             return NULL;
2260         }
2261 
2262         is_true = PyObject_IsTrue(res);
2263         Py_DECREF(res);
2264         if (is_true < 0) {
2265             return NULL;
2266         }
2267 
2268         if (is_true) {
2269             Py_RETURN_TRUE;
2270         }
2271     }
2272 
2273     self->task_must_cancel = 1;
2274     Py_XINCREF(msg);
2275     Py_XSETREF(self->task_cancel_msg, msg);
2276     Py_RETURN_TRUE;
2277 }
2278 
2279 /*[clinic input]
2280 _asyncio.Task.get_stack
2281 
2282     *
2283     limit: object = None
2284 
2285 Return the list of stack frames for this task's coroutine.
2286 
2287 If the coroutine is not done, this returns the stack where it is
2288 suspended.  If the coroutine has completed successfully or was
2289 cancelled, this returns an empty list.  If the coroutine was
2290 terminated by an exception, this returns the list of traceback
2291 frames.
2292 
2293 The frames are always ordered from oldest to newest.
2294 
2295 The optional limit gives the maximum number of frames to
2296 return; by default all available frames are returned.  Its
2297 meaning differs depending on whether a stack or a traceback is
2298 returned: the newest frames of a stack are returned, but the
2299 oldest frames of a traceback are returned.  (This matches the
2300 behavior of the traceback module.)
2301 
2302 For reasons beyond our control, only one stack frame is
2303 returned for a suspended coroutine.
2304 [clinic start generated code]*/
2305 
2306 static PyObject *
_asyncio_Task_get_stack_impl(TaskObj * self,PyObject * limit)2307 _asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
2308 /*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
2309 {
2310     return PyObject_CallFunctionObjArgs(
2311         asyncio_task_get_stack_func, self, limit, NULL);
2312 }
2313 
2314 /*[clinic input]
2315 _asyncio.Task.print_stack
2316 
2317     *
2318     limit: object = None
2319     file: object = None
2320 
2321 Print the stack or traceback for this task's coroutine.
2322 
2323 This produces output similar to that of the traceback module,
2324 for the frames retrieved by get_stack().  The limit argument
2325 is passed to get_stack().  The file argument is an I/O stream
2326 to which the output is written; by default output is written
2327 to sys.stderr.
2328 [clinic start generated code]*/
2329 
2330 static PyObject *
_asyncio_Task_print_stack_impl(TaskObj * self,PyObject * limit,PyObject * file)2331 _asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2332                                PyObject *file)
2333 /*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
2334 {
2335     return PyObject_CallFunctionObjArgs(
2336         asyncio_task_print_stack_func, self, limit, file, NULL);
2337 }
2338 
2339 /*[clinic input]
2340 _asyncio.Task.set_result
2341 
2342     result: object
2343     /
2344 [clinic start generated code]*/
2345 
2346 static PyObject *
_asyncio_Task_set_result(TaskObj * self,PyObject * result)2347 _asyncio_Task_set_result(TaskObj *self, PyObject *result)
2348 /*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2349 {
2350     PyErr_SetString(PyExc_RuntimeError,
2351                     "Task does not support set_result operation");
2352     return NULL;
2353 }
2354 
2355 /*[clinic input]
2356 _asyncio.Task.set_exception
2357 
2358     exception: object
2359     /
2360 [clinic start generated code]*/
2361 
2362 static PyObject *
_asyncio_Task_set_exception(TaskObj * self,PyObject * exception)2363 _asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2364 /*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2365 {
2366     PyErr_SetString(PyExc_RuntimeError,
2367                     "Task does not support set_exception operation");
2368     return NULL;
2369 }
2370 
2371 /*[clinic input]
2372 _asyncio.Task.get_coro
2373 [clinic start generated code]*/
2374 
2375 static PyObject *
_asyncio_Task_get_coro_impl(TaskObj * self)2376 _asyncio_Task_get_coro_impl(TaskObj *self)
2377 /*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2378 {
2379     Py_INCREF(self->task_coro);
2380     return self->task_coro;
2381 }
2382 
2383 /*[clinic input]
2384 _asyncio.Task.get_name
2385 [clinic start generated code]*/
2386 
2387 static PyObject *
_asyncio_Task_get_name_impl(TaskObj * self)2388 _asyncio_Task_get_name_impl(TaskObj *self)
2389 /*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2390 {
2391     if (self->task_name) {
2392         Py_INCREF(self->task_name);
2393         return self->task_name;
2394     }
2395 
2396     Py_RETURN_NONE;
2397 }
2398 
2399 /*[clinic input]
2400 _asyncio.Task.set_name
2401 
2402     value: object
2403     /
2404 [clinic start generated code]*/
2405 
2406 static PyObject *
_asyncio_Task_set_name(TaskObj * self,PyObject * value)2407 _asyncio_Task_set_name(TaskObj *self, PyObject *value)
2408 /*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2409 {
2410     if (!PyUnicode_CheckExact(value)) {
2411         value = PyObject_Str(value);
2412         if (value == NULL) {
2413             return NULL;
2414         }
2415     } else {
2416         Py_INCREF(value);
2417     }
2418 
2419     Py_XSETREF(self->task_name, value);
2420     Py_RETURN_NONE;
2421 }
2422 
2423 static void
TaskObj_finalize(TaskObj * task)2424 TaskObj_finalize(TaskObj *task)
2425 {
2426     _Py_IDENTIFIER(call_exception_handler);
2427     _Py_IDENTIFIER(task);
2428     _Py_IDENTIFIER(message);
2429     _Py_IDENTIFIER(source_traceback);
2430 
2431     PyObject *context;
2432     PyObject *message = NULL;
2433     PyObject *func;
2434     PyObject *error_type, *error_value, *error_traceback;
2435 
2436     if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2437         goto done;
2438     }
2439 
2440     /* Save the current exception, if any. */
2441     PyErr_Fetch(&error_type, &error_value, &error_traceback);
2442 
2443     context = PyDict_New();
2444     if (context == NULL) {
2445         goto finally;
2446     }
2447 
2448     message = PyUnicode_FromString("Task was destroyed but it is pending!");
2449     if (message == NULL) {
2450         goto finally;
2451     }
2452 
2453     if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2454         _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2455     {
2456         goto finally;
2457     }
2458 
2459     if (task->task_source_tb != NULL) {
2460         if (_PyDict_SetItemId(context, &PyId_source_traceback,
2461                               task->task_source_tb) < 0)
2462         {
2463             goto finally;
2464         }
2465     }
2466 
2467     func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2468     if (func != NULL) {
2469         PyObject *res = PyObject_CallOneArg(func, context);
2470         if (res == NULL) {
2471             PyErr_WriteUnraisable(func);
2472         }
2473         else {
2474             Py_DECREF(res);
2475         }
2476         Py_DECREF(func);
2477     }
2478 
2479 finally:
2480     Py_XDECREF(context);
2481     Py_XDECREF(message);
2482 
2483     /* Restore the saved exception. */
2484     PyErr_Restore(error_type, error_value, error_traceback);
2485 
2486 done:
2487     FutureObj_finalize((FutureObj*)task);
2488 }
2489 
2490 static PyObject *
task_cls_getitem(PyObject * cls,PyObject * type)2491 task_cls_getitem(PyObject *cls, PyObject *type)
2492 {
2493     Py_INCREF(cls);
2494     return cls;
2495 }
2496 
2497 static void TaskObj_dealloc(PyObject *);  /* Needs Task_CheckExact */
2498 
2499 static PyMethodDef TaskType_methods[] = {
2500     _ASYNCIO_FUTURE_RESULT_METHODDEF
2501     _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
2502     _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2503     _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2504     _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2505     _ASYNCIO_FUTURE_DONE_METHODDEF
2506     _ASYNCIO_TASK_SET_RESULT_METHODDEF
2507     _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
2508     _ASYNCIO_TASK_CANCEL_METHODDEF
2509     _ASYNCIO_TASK_GET_STACK_METHODDEF
2510     _ASYNCIO_TASK_PRINT_STACK_METHODDEF
2511     _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
2512     _ASYNCIO_TASK__REPR_INFO_METHODDEF
2513     _ASYNCIO_TASK_GET_NAME_METHODDEF
2514     _ASYNCIO_TASK_SET_NAME_METHODDEF
2515     _ASYNCIO_TASK_GET_CORO_METHODDEF
2516     {"__class_getitem__", task_cls_getitem, METH_O|METH_CLASS, NULL},
2517     {NULL, NULL}        /* Sentinel */
2518 };
2519 
2520 static PyGetSetDef TaskType_getsetlist[] = {
2521     FUTURE_COMMON_GETSETLIST
2522     {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2523                              (setter)TaskObj_set_log_destroy_pending, NULL},
2524     {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2525     {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2526     {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2527     {NULL} /* Sentinel */
2528 };
2529 
2530 static PyTypeObject TaskType = {
2531     PyVarObject_HEAD_INIT(NULL, 0)
2532     "_asyncio.Task",
2533     sizeof(TaskObj),                       /* tp_basicsize */
2534     .tp_base = &FutureType,
2535     .tp_dealloc = TaskObj_dealloc,
2536     .tp_as_async = &FutureType_as_async,
2537     .tp_repr = (reprfunc)FutureObj_repr,
2538     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
2539     .tp_doc = _asyncio_Task___init____doc__,
2540     .tp_traverse = (traverseproc)TaskObj_traverse,
2541     .tp_clear = (inquiry)TaskObj_clear,
2542     .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2543     .tp_iter = (getiterfunc)future_new_iter,
2544     .tp_methods = TaskType_methods,
2545     .tp_getset = TaskType_getsetlist,
2546     .tp_dictoffset = offsetof(TaskObj, dict),
2547     .tp_init = (initproc)_asyncio_Task___init__,
2548     .tp_new = PyType_GenericNew,
2549     .tp_finalize = (destructor)TaskObj_finalize,
2550 };
2551 
2552 static void
TaskObj_dealloc(PyObject * self)2553 TaskObj_dealloc(PyObject *self)
2554 {
2555     TaskObj *task = (TaskObj *)self;
2556 
2557     if (Task_CheckExact(self)) {
2558         /* When fut is subclass of Task, finalizer is called from
2559          * subtype_dealloc.
2560          */
2561         if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2562             // resurrected.
2563             return;
2564         }
2565     }
2566 
2567     PyObject_GC_UnTrack(self);
2568 
2569     if (task->task_weakreflist != NULL) {
2570         PyObject_ClearWeakRefs(self);
2571     }
2572 
2573     (void)TaskObj_clear(task);
2574     Py_TYPE(task)->tp_free(task);
2575 }
2576 
2577 static int
task_call_step_soon(TaskObj * task,PyObject * arg)2578 task_call_step_soon(TaskObj *task, PyObject *arg)
2579 {
2580     PyObject *cb = TaskStepMethWrapper_new(task, arg);
2581     if (cb == NULL) {
2582         return -1;
2583     }
2584 
2585     int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
2586     Py_DECREF(cb);
2587     return ret;
2588 }
2589 
2590 static PyObject *
task_set_error_soon(TaskObj * task,PyObject * et,const char * format,...)2591 task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2592 {
2593     PyObject* msg;
2594 
2595     va_list vargs;
2596 #ifdef HAVE_STDARG_PROTOTYPES
2597     va_start(vargs, format);
2598 #else
2599     va_start(vargs);
2600 #endif
2601     msg = PyUnicode_FromFormatV(format, vargs);
2602     va_end(vargs);
2603 
2604     if (msg == NULL) {
2605         return NULL;
2606     }
2607 
2608     PyObject *e = PyObject_CallOneArg(et, msg);
2609     Py_DECREF(msg);
2610     if (e == NULL) {
2611         return NULL;
2612     }
2613 
2614     if (task_call_step_soon(task, e) == -1) {
2615         Py_DECREF(e);
2616         return NULL;
2617     }
2618 
2619     Py_DECREF(e);
2620     Py_RETURN_NONE;
2621 }
2622 
2623 static PyObject *
task_step_impl(TaskObj * task,PyObject * exc)2624 task_step_impl(TaskObj *task, PyObject *exc)
2625 {
2626     int res;
2627     int clear_exc = 0;
2628     PyObject *result = NULL;
2629     PyObject *coro;
2630     PyObject *o;
2631 
2632     if (task->task_state != STATE_PENDING) {
2633         PyErr_Format(asyncio_InvalidStateError,
2634                      "_step(): already done: %R %R",
2635                      task,
2636                      exc ? exc : Py_None);
2637         goto fail;
2638     }
2639 
2640     if (task->task_must_cancel) {
2641         assert(exc != Py_None);
2642 
2643         if (exc) {
2644             /* Check if exc is a CancelledError */
2645             res = PyObject_IsInstance(exc, asyncio_CancelledError);
2646             if (res == -1) {
2647                 /* An error occurred, abort */
2648                 goto fail;
2649             }
2650             if (res == 0) {
2651                 /* exc is not CancelledError; reset it to NULL */
2652                 exc = NULL;
2653             }
2654         }
2655 
2656         if (!exc) {
2657             /* exc was not a CancelledError */
2658             exc = create_cancelled_error(task->task_cancel_msg);
2659 
2660             if (!exc) {
2661                 goto fail;
2662             }
2663             clear_exc = 1;
2664         }
2665 
2666         task->task_must_cancel = 0;
2667     }
2668 
2669     Py_CLEAR(task->task_fut_waiter);
2670 
2671     coro = task->task_coro;
2672     if (coro == NULL) {
2673         PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2674         if (clear_exc) {
2675             /* We created 'exc' during this call */
2676             Py_DECREF(exc);
2677         }
2678         return NULL;
2679     }
2680 
2681     if (exc == NULL) {
2682         if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2683             result = _PyGen_Send((PyGenObject*)coro, Py_None);
2684         }
2685         else {
2686             result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None);
2687         }
2688     }
2689     else {
2690         result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
2691         if (clear_exc) {
2692             /* We created 'exc' during this call */
2693             Py_DECREF(exc);
2694         }
2695     }
2696 
2697     if (result == NULL) {
2698         PyObject *et, *ev, *tb;
2699 
2700         if (_PyGen_FetchStopIterationValue(&o) == 0) {
2701             /* The error is StopIteration and that means that
2702                the underlying coroutine has resolved */
2703 
2704             PyObject *res;
2705             if (task->task_must_cancel) {
2706                 // Task is cancelled right before coro stops.
2707                 task->task_must_cancel = 0;
2708                 res = future_cancel((FutureObj*)task, task->task_cancel_msg);
2709             }
2710             else {
2711                 res = future_set_result((FutureObj*)task, o);
2712             }
2713 
2714             Py_DECREF(o);
2715 
2716             if (res == NULL) {
2717                 return NULL;
2718             }
2719             Py_DECREF(res);
2720             Py_RETURN_NONE;
2721         }
2722 
2723         if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2724             /* CancelledError */
2725             PyErr_Fetch(&et, &ev, &tb);
2726 
2727             FutureObj *fut = (FutureObj*)task;
2728             _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
2729             exc_state->exc_type = et;
2730             exc_state->exc_value = ev;
2731             exc_state->exc_traceback = tb;
2732 
2733             return future_cancel(fut, NULL);
2734         }
2735 
2736         /* Some other exception; pop it and call Task.set_exception() */
2737         PyErr_Fetch(&et, &ev, &tb);
2738 
2739         assert(et);
2740         if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2741             PyErr_NormalizeException(&et, &ev, &tb);
2742         }
2743         if (tb != NULL) {
2744             PyException_SetTraceback(ev, tb);
2745         }
2746         o = future_set_exception((FutureObj*)task, ev);
2747         if (!o) {
2748             /* An exception in Task.set_exception() */
2749             Py_DECREF(et);
2750             Py_XDECREF(tb);
2751             Py_XDECREF(ev);
2752             goto fail;
2753         }
2754         assert(o == Py_None);
2755         Py_DECREF(o);
2756 
2757         if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2758             PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2759         {
2760             /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
2761             PyErr_Restore(et, ev, tb);
2762             goto fail;
2763         }
2764 
2765         Py_DECREF(et);
2766         Py_XDECREF(tb);
2767         Py_XDECREF(ev);
2768 
2769         Py_RETURN_NONE;
2770     }
2771 
2772     if (result == (PyObject*)task) {
2773         /* We have a task that wants to await on itself */
2774         goto self_await;
2775     }
2776 
2777     /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2778     if (Future_CheckExact(result) || Task_CheckExact(result)) {
2779         PyObject *wrapper;
2780         PyObject *res;
2781         FutureObj *fut = (FutureObj*)result;
2782 
2783         /* Check if `result` future is attached to a different loop */
2784         if (fut->fut_loop != task->task_loop) {
2785             goto different_loop;
2786         }
2787 
2788         if (!fut->fut_blocking) {
2789             goto yield_insteadof_yf;
2790         }
2791 
2792         fut->fut_blocking = 0;
2793 
2794         /* result.add_done_callback(task._wakeup) */
2795         wrapper = TaskWakeupMethWrapper_new(task);
2796         if (wrapper == NULL) {
2797             goto fail;
2798         }
2799         res = future_add_done_callback(
2800             (FutureObj*)result, wrapper, task->task_context);
2801         Py_DECREF(wrapper);
2802         if (res == NULL) {
2803             goto fail;
2804         }
2805         Py_DECREF(res);
2806 
2807         /* task._fut_waiter = result */
2808         task->task_fut_waiter = result;  /* no incref is necessary */
2809 
2810         if (task->task_must_cancel) {
2811             PyObject *r;
2812             int is_true;
2813             r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2814                                              task->task_cancel_msg);
2815             if (r == NULL) {
2816                 return NULL;
2817             }
2818             is_true = PyObject_IsTrue(r);
2819             Py_DECREF(r);
2820             if (is_true < 0) {
2821                 return NULL;
2822             }
2823             else if (is_true) {
2824                 task->task_must_cancel = 0;
2825             }
2826         }
2827 
2828         Py_RETURN_NONE;
2829     }
2830 
2831     /* Check if `result` is None */
2832     if (result == Py_None) {
2833         /* Bare yield relinquishes control for one event loop iteration. */
2834         if (task_call_step_soon(task, NULL)) {
2835             goto fail;
2836         }
2837         return result;
2838     }
2839 
2840     /* Check if `result` is a Future-compatible object */
2841     if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2842         goto fail;
2843     }
2844     if (o != NULL && o != Py_None) {
2845         /* `result` is a Future-compatible object */
2846         PyObject *wrapper;
2847         PyObject *res;
2848 
2849         int blocking = PyObject_IsTrue(o);
2850         Py_DECREF(o);
2851         if (blocking < 0) {
2852             goto fail;
2853         }
2854 
2855         /* Check if `result` future is attached to a different loop */
2856         PyObject *oloop = get_future_loop(result);
2857         if (oloop == NULL) {
2858             goto fail;
2859         }
2860         if (oloop != task->task_loop) {
2861             Py_DECREF(oloop);
2862             goto different_loop;
2863         }
2864         Py_DECREF(oloop);
2865 
2866         if (!blocking) {
2867             goto yield_insteadof_yf;
2868         }
2869 
2870         /* result._asyncio_future_blocking = False */
2871         if (_PyObject_SetAttrId(
2872                 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2873             goto fail;
2874         }
2875 
2876         wrapper = TaskWakeupMethWrapper_new(task);
2877         if (wrapper == NULL) {
2878             goto fail;
2879         }
2880 
2881         /* result.add_done_callback(task._wakeup) */
2882         PyObject *add_cb = _PyObject_GetAttrId(
2883             result, &PyId_add_done_callback);
2884         if (add_cb == NULL) {
2885             Py_DECREF(wrapper);
2886             goto fail;
2887         }
2888         PyObject *stack[2];
2889         stack[0] = wrapper;
2890         stack[1] = (PyObject *)task->task_context;
2891         res = PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
2892         Py_DECREF(add_cb);
2893         Py_DECREF(wrapper);
2894         if (res == NULL) {
2895             goto fail;
2896         }
2897         Py_DECREF(res);
2898 
2899         /* task._fut_waiter = result */
2900         task->task_fut_waiter = result;  /* no incref is necessary */
2901 
2902         if (task->task_must_cancel) {
2903             PyObject *r;
2904             int is_true;
2905             r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2906                                              task->task_cancel_msg);
2907             if (r == NULL) {
2908                 return NULL;
2909             }
2910             is_true = PyObject_IsTrue(r);
2911             Py_DECREF(r);
2912             if (is_true < 0) {
2913                 return NULL;
2914             }
2915             else if (is_true) {
2916                 task->task_must_cancel = 0;
2917             }
2918         }
2919 
2920         Py_RETURN_NONE;
2921     }
2922 
2923     Py_XDECREF(o);
2924     /* Check if `result` is a generator */
2925     res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2926     if (res < 0) {
2927         goto fail;
2928     }
2929     if (res) {
2930         /* `result` is a generator */
2931         o = task_set_error_soon(
2932             task, PyExc_RuntimeError,
2933             "yield was used instead of yield from for "
2934             "generator in task %R with %R", task, result);
2935         Py_DECREF(result);
2936         return o;
2937     }
2938 
2939     /* The `result` is none of the above */
2940     o = task_set_error_soon(
2941         task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2942     Py_DECREF(result);
2943     return o;
2944 
2945 self_await:
2946     o = task_set_error_soon(
2947         task, PyExc_RuntimeError,
2948         "Task cannot await on itself: %R", task);
2949     Py_DECREF(result);
2950     return o;
2951 
2952 yield_insteadof_yf:
2953     o = task_set_error_soon(
2954         task, PyExc_RuntimeError,
2955         "yield was used instead of yield from "
2956         "in task %R with %R",
2957         task, result);
2958     Py_DECREF(result);
2959     return o;
2960 
2961 different_loop:
2962     o = task_set_error_soon(
2963         task, PyExc_RuntimeError,
2964         "Task %R got Future %R attached to a different loop",
2965         task, result);
2966     Py_DECREF(result);
2967     return o;
2968 
2969 fail:
2970     Py_XDECREF(result);
2971     return NULL;
2972 }
2973 
2974 static PyObject *
task_step(TaskObj * task,PyObject * exc)2975 task_step(TaskObj *task, PyObject *exc)
2976 {
2977     PyObject *res;
2978 
2979     if (enter_task(task->task_loop, (PyObject*)task) < 0) {
2980         return NULL;
2981     }
2982 
2983     res = task_step_impl(task, exc);
2984 
2985     if (res == NULL) {
2986         PyObject *et, *ev, *tb;
2987         PyErr_Fetch(&et, &ev, &tb);
2988         leave_task(task->task_loop, (PyObject*)task);
2989         _PyErr_ChainExceptions(et, ev, tb);
2990         return NULL;
2991     }
2992     else {
2993         if (leave_task(task->task_loop, (PyObject*)task) < 0) {
2994             Py_DECREF(res);
2995             return NULL;
2996         }
2997         else {
2998             return res;
2999         }
3000     }
3001 }
3002 
3003 static PyObject *
task_wakeup(TaskObj * task,PyObject * o)3004 task_wakeup(TaskObj *task, PyObject *o)
3005 {
3006     PyObject *et, *ev, *tb;
3007     PyObject *result;
3008     assert(o);
3009 
3010     if (Future_CheckExact(o) || Task_CheckExact(o)) {
3011         PyObject *fut_result = NULL;
3012         int res = future_get_result((FutureObj*)o, &fut_result);
3013 
3014         switch(res) {
3015         case -1:
3016             assert(fut_result == NULL);
3017             break; /* exception raised */
3018         case 0:
3019             Py_DECREF(fut_result);
3020             return task_step(task, NULL);
3021         default:
3022             assert(res == 1);
3023             result = task_step(task, fut_result);
3024             Py_DECREF(fut_result);
3025             return result;
3026         }
3027     }
3028     else {
3029         PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
3030         if (fut_result != NULL) {
3031             Py_DECREF(fut_result);
3032             return task_step(task, NULL);
3033         }
3034         /* exception raised */
3035     }
3036 
3037     PyErr_Fetch(&et, &ev, &tb);
3038     if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
3039         PyErr_NormalizeException(&et, &ev, &tb);
3040     }
3041 
3042     result = task_step(task, ev);
3043 
3044     Py_DECREF(et);
3045     Py_XDECREF(tb);
3046     Py_XDECREF(ev);
3047 
3048     return result;
3049 }
3050 
3051 
3052 /*********************** Functions **************************/
3053 
3054 
3055 /*[clinic input]
3056 _asyncio._get_running_loop
3057 
3058 Return the running event loop or None.
3059 
3060 This is a low-level function intended to be used by event loops.
3061 This function is thread-specific.
3062 
3063 [clinic start generated code]*/
3064 
3065 static PyObject *
_asyncio__get_running_loop_impl(PyObject * module)3066 _asyncio__get_running_loop_impl(PyObject *module)
3067 /*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3068 {
3069     PyObject *loop;
3070     if (get_running_loop(&loop)) {
3071         return NULL;
3072     }
3073     if (loop == NULL) {
3074         /* There's no currently running event loop */
3075         Py_RETURN_NONE;
3076     }
3077     return loop;
3078 }
3079 
3080 /*[clinic input]
3081 _asyncio._set_running_loop
3082     loop: 'O'
3083     /
3084 
3085 Set the running event loop.
3086 
3087 This is a low-level function intended to be used by event loops.
3088 This function is thread-specific.
3089 [clinic start generated code]*/
3090 
3091 static PyObject *
_asyncio__set_running_loop(PyObject * module,PyObject * loop)3092 _asyncio__set_running_loop(PyObject *module, PyObject *loop)
3093 /*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3094 {
3095     if (set_running_loop(loop)) {
3096         return NULL;
3097     }
3098     Py_RETURN_NONE;
3099 }
3100 
3101 /*[clinic input]
3102 _asyncio.get_event_loop
3103 
3104 Return an asyncio event loop.
3105 
3106 When called from a coroutine or a callback (e.g. scheduled with
3107 call_soon or similar API), this function will always return the
3108 running event loop.
3109 
3110 If there is no running event loop set, the function will return
3111 the result of `get_event_loop_policy().get_event_loop()` call.
3112 [clinic start generated code]*/
3113 
3114 static PyObject *
_asyncio_get_event_loop_impl(PyObject * module)3115 _asyncio_get_event_loop_impl(PyObject *module)
3116 /*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3117 {
3118     return get_event_loop();
3119 }
3120 
3121 /*[clinic input]
3122 _asyncio.get_running_loop
3123 
3124 Return the running event loop.  Raise a RuntimeError if there is none.
3125 
3126 This function is thread-specific.
3127 [clinic start generated code]*/
3128 
3129 static PyObject *
_asyncio_get_running_loop_impl(PyObject * module)3130 _asyncio_get_running_loop_impl(PyObject *module)
3131 /*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3132 {
3133     PyObject *loop;
3134     if (get_running_loop(&loop)) {
3135         return NULL;
3136     }
3137     if (loop == NULL) {
3138         /* There's no currently running event loop */
3139         PyErr_SetString(
3140             PyExc_RuntimeError, "no running event loop");
3141     }
3142     return loop;
3143 }
3144 
3145 /*[clinic input]
3146 _asyncio._register_task
3147 
3148     task: object
3149 
3150 Register a new task in asyncio as executed by loop.
3151 
3152 Returns None.
3153 [clinic start generated code]*/
3154 
3155 static PyObject *
_asyncio__register_task_impl(PyObject * module,PyObject * task)3156 _asyncio__register_task_impl(PyObject *module, PyObject *task)
3157 /*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
3158 {
3159     if (register_task(task) < 0) {
3160         return NULL;
3161     }
3162     Py_RETURN_NONE;
3163 }
3164 
3165 
3166 /*[clinic input]
3167 _asyncio._unregister_task
3168 
3169     task: object
3170 
3171 Unregister a task.
3172 
3173 Returns None.
3174 [clinic start generated code]*/
3175 
3176 static PyObject *
_asyncio__unregister_task_impl(PyObject * module,PyObject * task)3177 _asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3178 /*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
3179 {
3180     if (unregister_task(task) < 0) {
3181         return NULL;
3182     }
3183     Py_RETURN_NONE;
3184 }
3185 
3186 
3187 /*[clinic input]
3188 _asyncio._enter_task
3189 
3190     loop: object
3191     task: object
3192 
3193 Enter into task execution or resume suspended task.
3194 
3195 Task belongs to loop.
3196 
3197 Returns None.
3198 [clinic start generated code]*/
3199 
3200 static PyObject *
_asyncio__enter_task_impl(PyObject * module,PyObject * loop,PyObject * task)3201 _asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3202 /*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3203 {
3204     if (enter_task(loop, task) < 0) {
3205         return NULL;
3206     }
3207     Py_RETURN_NONE;
3208 }
3209 
3210 
3211 /*[clinic input]
3212 _asyncio._leave_task
3213 
3214     loop: object
3215     task: object
3216 
3217 Leave task execution or suspend a task.
3218 
3219 Task belongs to loop.
3220 
3221 Returns None.
3222 [clinic start generated code]*/
3223 
3224 static PyObject *
_asyncio__leave_task_impl(PyObject * module,PyObject * loop,PyObject * task)3225 _asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3226 /*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3227 {
3228     if (leave_task(loop, task) < 0) {
3229         return NULL;
3230     }
3231     Py_RETURN_NONE;
3232 }
3233 
3234 
3235 /*********************** PyRunningLoopHolder ********************/
3236 
3237 
3238 static PyRunningLoopHolder *
new_running_loop_holder(PyObject * loop)3239 new_running_loop_holder(PyObject *loop)
3240 {
3241     PyRunningLoopHolder *rl = PyObject_New(
3242         PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3243     if (rl == NULL) {
3244         return NULL;
3245     }
3246 
3247 #if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3248     rl->rl_pid = getpid();
3249 #endif
3250 
3251     Py_INCREF(loop);
3252     rl->rl_loop = loop;
3253 
3254     return rl;
3255 }
3256 
3257 
3258 static void
PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder * rl)3259 PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3260 {
3261     Py_CLEAR(rl->rl_loop);
3262     PyObject_Free(rl);
3263 }
3264 
3265 
3266 static PyTypeObject PyRunningLoopHolder_Type = {
3267     PyVarObject_HEAD_INIT(NULL, 0)
3268     "_RunningLoopHolder",
3269     sizeof(PyRunningLoopHolder),
3270     .tp_getattro = PyObject_GenericGetAttr,
3271     .tp_flags = Py_TPFLAGS_DEFAULT,
3272     .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3273 };
3274 
3275 
3276 /*********************** Module **************************/
3277 
3278 
3279 static void
module_free_freelists(void)3280 module_free_freelists(void)
3281 {
3282     PyObject *next;
3283     PyObject *current;
3284 
3285     next = (PyObject*) fi_freelist;
3286     while (next != NULL) {
3287         assert(fi_freelist_len > 0);
3288         fi_freelist_len--;
3289 
3290         current = next;
3291         next = (PyObject*) ((futureiterobject*) current)->future;
3292         PyObject_GC_Del(current);
3293     }
3294     assert(fi_freelist_len == 0);
3295     fi_freelist = NULL;
3296 }
3297 
3298 
3299 static void
module_free(void * m)3300 module_free(void *m)
3301 {
3302     Py_CLEAR(asyncio_mod);
3303     Py_CLEAR(traceback_extract_stack);
3304     Py_CLEAR(asyncio_future_repr_info_func);
3305     Py_CLEAR(asyncio_get_event_loop_policy);
3306     Py_CLEAR(asyncio_iscoroutine_func);
3307     Py_CLEAR(asyncio_task_get_stack_func);
3308     Py_CLEAR(asyncio_task_print_stack_func);
3309     Py_CLEAR(asyncio_task_repr_info_func);
3310     Py_CLEAR(asyncio_InvalidStateError);
3311     Py_CLEAR(asyncio_CancelledError);
3312 
3313     Py_CLEAR(all_tasks);
3314     Py_CLEAR(current_tasks);
3315     Py_CLEAR(iscoroutine_typecache);
3316 
3317     Py_CLEAR(context_kwname);
3318 
3319     module_free_freelists();
3320 
3321     module_initialized = 0;
3322 }
3323 
3324 static int
module_init(void)3325 module_init(void)
3326 {
3327     PyObject *module = NULL;
3328 
3329     asyncio_mod = PyImport_ImportModule("asyncio");
3330     if (asyncio_mod == NULL) {
3331         goto fail;
3332     }
3333     if (module_initialized != 0) {
3334         return 0;
3335     }
3336     else {
3337         module_initialized = 1;
3338     }
3339 
3340     current_tasks = PyDict_New();
3341     if (current_tasks == NULL) {
3342         goto fail;
3343     }
3344 
3345     iscoroutine_typecache = PySet_New(NULL);
3346     if (iscoroutine_typecache == NULL) {
3347         goto fail;
3348     }
3349 
3350 
3351     context_kwname = Py_BuildValue("(s)", "context");
3352     if (context_kwname == NULL) {
3353         goto fail;
3354     }
3355 
3356 #define WITH_MOD(NAME) \
3357     Py_CLEAR(module); \
3358     module = PyImport_ImportModule(NAME); \
3359     if (module == NULL) { \
3360         goto fail; \
3361     }
3362 
3363 #define GET_MOD_ATTR(VAR, NAME) \
3364     VAR = PyObject_GetAttrString(module, NAME); \
3365     if (VAR == NULL) { \
3366         goto fail; \
3367     }
3368 
3369     WITH_MOD("asyncio.events")
3370     GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
3371 
3372     WITH_MOD("asyncio.base_futures")
3373     GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
3374 
3375     WITH_MOD("asyncio.exceptions")
3376     GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3377     GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3378 
3379     WITH_MOD("asyncio.base_tasks")
3380     GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3381     GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3382     GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3383 
3384     WITH_MOD("asyncio.coroutines")
3385     GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3386 
3387     WITH_MOD("traceback")
3388     GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3389 
3390     PyObject *weak_set;
3391     WITH_MOD("weakref")
3392     GET_MOD_ATTR(weak_set, "WeakSet");
3393     all_tasks = PyObject_CallNoArgs(weak_set);
3394     Py_CLEAR(weak_set);
3395     if (all_tasks == NULL) {
3396         goto fail;
3397     }
3398 
3399     Py_DECREF(module);
3400     return 0;
3401 
3402 fail:
3403     Py_CLEAR(module);
3404     module_free(NULL);
3405     return -1;
3406 
3407 #undef WITH_MOD
3408 #undef GET_MOD_ATTR
3409 }
3410 
3411 PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
3412 
3413 static PyMethodDef asyncio_methods[] = {
3414     _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3415     _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3416     _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3417     _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
3418     _ASYNCIO__REGISTER_TASK_METHODDEF
3419     _ASYNCIO__UNREGISTER_TASK_METHODDEF
3420     _ASYNCIO__ENTER_TASK_METHODDEF
3421     _ASYNCIO__LEAVE_TASK_METHODDEF
3422     {NULL, NULL}
3423 };
3424 
3425 static struct PyModuleDef _asynciomodule = {
3426     PyModuleDef_HEAD_INIT,      /* m_base */
3427     "_asyncio",                 /* m_name */
3428     module_doc,                 /* m_doc */
3429     -1,                         /* m_size */
3430     asyncio_methods,            /* m_methods */
3431     NULL,                       /* m_slots */
3432     NULL,                       /* m_traverse */
3433     NULL,                       /* m_clear */
3434     (freefunc)module_free       /* m_free */
3435 };
3436 
3437 
3438 PyMODINIT_FUNC
PyInit__asyncio(void)3439 PyInit__asyncio(void)
3440 {
3441     if (module_init() < 0) {
3442         return NULL;
3443     }
3444     if (PyType_Ready(&FutureIterType) < 0) {
3445         return NULL;
3446     }
3447     if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
3448         return NULL;
3449     }
3450     if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
3451         return NULL;
3452     }
3453     if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3454         return NULL;
3455     }
3456 
3457     PyObject *m = PyModule_Create(&_asynciomodule);
3458     if (m == NULL) {
3459         return NULL;
3460     }
3461 
3462     /* FutureType and TaskType are made ready by PyModule_AddType() calls below. */
3463     if (PyModule_AddType(m, &FutureType) < 0) {
3464         Py_DECREF(m);
3465         return NULL;
3466     }
3467 
3468     if (PyModule_AddType(m, &TaskType) < 0) {
3469         Py_DECREF(m);
3470         return NULL;
3471     }
3472 
3473     Py_INCREF(all_tasks);
3474     if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3475         Py_DECREF(all_tasks);
3476         Py_DECREF(m);
3477         return NULL;
3478     }
3479 
3480     Py_INCREF(current_tasks);
3481     if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3482         Py_DECREF(current_tasks);
3483         Py_DECREF(m);
3484         return NULL;
3485     }
3486 
3487     return m;
3488 }
3489