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