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