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