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