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