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