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