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