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(add_done_callback);
13 _Py_IDENTIFIER(call_soon);
14 _Py_IDENTIFIER(cancel);
15 _Py_IDENTIFIER(send);
16 _Py_IDENTIFIER(throw);
17 _Py_IDENTIFIER(_step);
18 _Py_IDENTIFIER(_schedule_callbacks);
19 _Py_IDENTIFIER(_wakeup);
20
21
22 /* State of the _asyncio module */
23 static PyObject *all_tasks;
24 static PyObject *current_tasks;
25 static PyObject *traceback_extract_stack;
26 static PyObject *asyncio_get_event_loop;
27 static PyObject *asyncio_future_repr_info_func;
28 static PyObject *asyncio_task_repr_info_func;
29 static PyObject *asyncio_task_get_stack_func;
30 static PyObject *asyncio_task_print_stack_func;
31 static PyObject *asyncio_InvalidStateError;
32 static PyObject *asyncio_CancelledError;
33 static PyObject *inspect_isgenerator;
34
35
36 typedef enum {
37 STATE_PENDING,
38 STATE_CANCELLED,
39 STATE_FINISHED
40 } fut_state;
41
42 #define FutureObj_HEAD(prefix) \
43 PyObject_HEAD \
44 PyObject *prefix##_loop; \
45 PyObject *prefix##_callbacks; \
46 PyObject *prefix##_exception; \
47 PyObject *prefix##_result; \
48 PyObject *prefix##_source_tb; \
49 fut_state prefix##_state; \
50 int prefix##_log_tb; \
51 int prefix##_blocking; \
52 PyObject *dict; \
53 PyObject *prefix##_weakreflist;
54
55 typedef struct {
56 FutureObj_HEAD(fut)
57 } FutureObj;
58
59 typedef struct {
60 FutureObj_HEAD(task)
61 PyObject *task_fut_waiter;
62 PyObject *task_coro;
63 int task_must_cancel;
64 int task_log_destroy_pending;
65 } TaskObj;
66
67 typedef struct {
68 PyObject_HEAD
69 TaskObj *sw_task;
70 PyObject *sw_arg;
71 } TaskSendMethWrapper;
72
73 typedef struct {
74 PyObject_HEAD
75 TaskObj *ww_task;
76 } TaskWakeupMethWrapper;
77
78
79 #include "clinic/_asynciomodule.c.h"
80
81
82 /*[clinic input]
83 class _asyncio.Future "FutureObj *" "&Future_Type"
84 [clinic start generated code]*/
85 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
86
87 /* Get FutureIter from Future */
88 static PyObject* future_new_iter(PyObject *);
89 static inline int future_call_schedule_callbacks(FutureObj *);
90
91 static int
future_schedule_callbacks(FutureObj * fut)92 future_schedule_callbacks(FutureObj *fut)
93 {
94 Py_ssize_t len;
95 PyObject* iters;
96 int i;
97
98 if (fut->fut_callbacks == NULL) {
99 PyErr_SetString(PyExc_RuntimeError, "NULL callbacks");
100 return -1;
101 }
102
103 len = PyList_GET_SIZE(fut->fut_callbacks);
104 if (len == 0) {
105 return 0;
106 }
107
108 iters = PyList_GetSlice(fut->fut_callbacks, 0, len);
109 if (iters == NULL) {
110 return -1;
111 }
112 if (PyList_SetSlice(fut->fut_callbacks, 0, len, NULL) < 0) {
113 Py_DECREF(iters);
114 return -1;
115 }
116
117 for (i = 0; i < len; i++) {
118 PyObject *handle = NULL;
119 PyObject *cb = PyList_GET_ITEM(iters, i);
120
121 handle = _PyObject_CallMethodId(
122 fut->fut_loop, &PyId_call_soon, "OO", cb, fut, NULL);
123
124 if (handle == NULL) {
125 Py_DECREF(iters);
126 return -1;
127 }
128 else {
129 Py_DECREF(handle);
130 }
131 }
132
133 Py_DECREF(iters);
134 return 0;
135 }
136
137 static int
future_init(FutureObj * fut,PyObject * loop)138 future_init(FutureObj *fut, PyObject *loop)
139 {
140 PyObject *res = NULL;
141 _Py_IDENTIFIER(get_debug);
142
143 if (loop == NULL || loop == Py_None) {
144 loop = PyObject_CallObject(asyncio_get_event_loop, NULL);
145 if (loop == NULL) {
146 return -1;
147 }
148 }
149 else {
150 Py_INCREF(loop);
151 }
152 Py_CLEAR(fut->fut_loop);
153 fut->fut_loop = loop;
154
155 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
156 if (res == NULL) {
157 return -1;
158 }
159 if (PyObject_IsTrue(res)) {
160 Py_CLEAR(res);
161 fut->fut_source_tb = PyObject_CallObject(traceback_extract_stack, NULL);
162 if (fut->fut_source_tb == NULL) {
163 return -1;
164 }
165 }
166 else {
167 Py_CLEAR(res);
168 }
169
170 fut->fut_callbacks = PyList_New(0);
171 if (fut->fut_callbacks == NULL) {
172 return -1;
173 }
174
175 return 0;
176 }
177
178 static PyObject *
future_set_result(FutureObj * fut,PyObject * res)179 future_set_result(FutureObj *fut, PyObject *res)
180 {
181 if (fut->fut_state != STATE_PENDING) {
182 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
183 return NULL;
184 }
185
186 Py_INCREF(res);
187 fut->fut_result = res;
188 fut->fut_state = STATE_FINISHED;
189
190 if (future_call_schedule_callbacks(fut) == -1) {
191 return NULL;
192 }
193 Py_RETURN_NONE;
194 }
195
196 static PyObject *
future_set_exception(FutureObj * fut,PyObject * exc)197 future_set_exception(FutureObj *fut, PyObject *exc)
198 {
199 PyObject *exc_val = NULL;
200
201 if (fut->fut_state != STATE_PENDING) {
202 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
203 return NULL;
204 }
205
206 if (PyExceptionClass_Check(exc)) {
207 exc_val = PyObject_CallObject(exc, NULL);
208 if (exc_val == NULL) {
209 return NULL;
210 }
211 }
212 else {
213 exc_val = exc;
214 Py_INCREF(exc_val);
215 }
216 if (!PyExceptionInstance_Check(exc_val)) {
217 Py_DECREF(exc_val);
218 PyErr_SetString(PyExc_TypeError, "invalid exception object");
219 return NULL;
220 }
221 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
222 Py_DECREF(exc_val);
223 PyErr_SetString(PyExc_TypeError,
224 "StopIteration interacts badly with generators "
225 "and cannot be raised into a Future");
226 return NULL;
227 }
228
229 fut->fut_exception = exc_val;
230 fut->fut_state = STATE_FINISHED;
231
232 if (future_call_schedule_callbacks(fut) == -1) {
233 return NULL;
234 }
235
236 fut->fut_log_tb = 1;
237 Py_RETURN_NONE;
238 }
239
240 static int
future_get_result(FutureObj * fut,PyObject ** result)241 future_get_result(FutureObj *fut, PyObject **result)
242 {
243 PyObject *exc;
244
245 if (fut->fut_state == STATE_CANCELLED) {
246 exc = _PyObject_CallNoArg(asyncio_CancelledError);
247 if (exc == NULL) {
248 return -1;
249 }
250 *result = exc;
251 return 1;
252 }
253
254 if (fut->fut_state != STATE_FINISHED) {
255 PyObject *msg = PyUnicode_FromString("Result is not ready.");
256 if (msg == NULL) {
257 return -1;
258 }
259
260 exc = _PyObject_CallArg1(asyncio_InvalidStateError, msg);
261 Py_DECREF(msg);
262 if (exc == NULL) {
263 return -1;
264 }
265
266 *result = exc;
267 return 1;
268 }
269
270 fut->fut_log_tb = 0;
271 if (fut->fut_exception != NULL) {
272 Py_INCREF(fut->fut_exception);
273 *result = fut->fut_exception;
274 return 1;
275 }
276
277 Py_INCREF(fut->fut_result);
278 *result = fut->fut_result;
279 return 0;
280 }
281
282 static PyObject *
future_add_done_callback(FutureObj * fut,PyObject * arg)283 future_add_done_callback(FutureObj *fut, PyObject *arg)
284 {
285 if (fut->fut_state != STATE_PENDING) {
286 PyObject *handle = _PyObject_CallMethodId(
287 fut->fut_loop, &PyId_call_soon, "OO", arg, fut, NULL);
288
289 if (handle == NULL) {
290 return NULL;
291 }
292 else {
293 Py_DECREF(handle);
294 }
295 }
296 else {
297 int err = PyList_Append(fut->fut_callbacks, arg);
298 if (err != 0) {
299 return NULL;
300 }
301 }
302 Py_RETURN_NONE;
303 }
304
305 static PyObject *
future_cancel(FutureObj * fut)306 future_cancel(FutureObj *fut)
307 {
308 if (fut->fut_state != STATE_PENDING) {
309 Py_RETURN_FALSE;
310 }
311 fut->fut_state = STATE_CANCELLED;
312
313 if (future_call_schedule_callbacks(fut) == -1) {
314 return NULL;
315 }
316
317 Py_RETURN_TRUE;
318 }
319
320 /*[clinic input]
321 _asyncio.Future.__init__
322
323 *
324 loop: 'O' = NULL
325
326 This class is *almost* compatible with concurrent.futures.Future.
327
328 Differences:
329
330 - result() and exception() do not take a timeout argument and
331 raise an exception when the future isn't done yet.
332
333 - Callbacks registered with add_done_callback() are always called
334 via the event loop's call_soon_threadsafe().
335
336 - This class is not compatible with the wait() and as_completed()
337 methods in the concurrent.futures package.
338 [clinic start generated code]*/
339
340 static int
_asyncio_Future___init___impl(FutureObj * self,PyObject * loop)341 _asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
342 /*[clinic end generated code: output=9ed75799eaccb5d6 input=8e1681f23605be2d]*/
343
344 {
345 return future_init(self, loop);
346 }
347
348 static int
FutureObj_clear(FutureObj * fut)349 FutureObj_clear(FutureObj *fut)
350 {
351 Py_CLEAR(fut->fut_loop);
352 Py_CLEAR(fut->fut_callbacks);
353 Py_CLEAR(fut->fut_result);
354 Py_CLEAR(fut->fut_exception);
355 Py_CLEAR(fut->fut_source_tb);
356 Py_CLEAR(fut->dict);
357 return 0;
358 }
359
360 static int
FutureObj_traverse(FutureObj * fut,visitproc visit,void * arg)361 FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
362 {
363 Py_VISIT(fut->fut_loop);
364 Py_VISIT(fut->fut_callbacks);
365 Py_VISIT(fut->fut_result);
366 Py_VISIT(fut->fut_exception);
367 Py_VISIT(fut->fut_source_tb);
368 Py_VISIT(fut->dict);
369 return 0;
370 }
371
372 /*[clinic input]
373 _asyncio.Future.result
374
375 Return the result this future represents.
376
377 If the future has been cancelled, raises CancelledError. If the
378 future's result isn't yet available, raises InvalidStateError. If
379 the future is done and has an exception set, this exception is raised.
380 [clinic start generated code]*/
381
382 static PyObject *
_asyncio_Future_result_impl(FutureObj * self)383 _asyncio_Future_result_impl(FutureObj *self)
384 /*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
385 {
386 PyObject *result;
387 int res = future_get_result(self, &result);
388
389 if (res == -1) {
390 return NULL;
391 }
392
393 if (res == 0) {
394 return result;
395 }
396
397 assert(res == 1);
398
399 PyErr_SetObject(PyExceptionInstance_Class(result), result);
400 Py_DECREF(result);
401 return NULL;
402 }
403
404 /*[clinic input]
405 _asyncio.Future.exception
406
407 Return the exception that was set on this future.
408
409 The exception (or None if no exception was set) is returned only if
410 the future is done. If the future has been cancelled, raises
411 CancelledError. If the future isn't done yet, raises
412 InvalidStateError.
413 [clinic start generated code]*/
414
415 static PyObject *
_asyncio_Future_exception_impl(FutureObj * self)416 _asyncio_Future_exception_impl(FutureObj *self)
417 /*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
418 {
419 if (self->fut_state == STATE_CANCELLED) {
420 PyErr_SetString(asyncio_CancelledError, "");
421 return NULL;
422 }
423
424 if (self->fut_state != STATE_FINISHED) {
425 PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");
426 return NULL;
427 }
428
429 if (self->fut_exception != NULL) {
430 self->fut_log_tb = 0;
431 Py_INCREF(self->fut_exception);
432 return self->fut_exception;
433 }
434
435 Py_RETURN_NONE;
436 }
437
438 /*[clinic input]
439 _asyncio.Future.set_result
440
441 res: 'O'
442 /
443
444 Mark the future done and set its result.
445
446 If the future is already done when this method is called, raises
447 InvalidStateError.
448 [clinic start generated code]*/
449
450 static PyObject *
_asyncio_Future_set_result(FutureObj * self,PyObject * res)451 _asyncio_Future_set_result(FutureObj *self, PyObject *res)
452 /*[clinic end generated code: output=a620abfc2796bfb6 input=8619565e0503357e]*/
453 {
454 return future_set_result(self, res);
455 }
456
457 /*[clinic input]
458 _asyncio.Future.set_exception
459
460 exception: 'O'
461 /
462
463 Mark the future done and set an exception.
464
465 If the future is already done when this method is called, raises
466 InvalidStateError.
467 [clinic start generated code]*/
468
469 static PyObject *
_asyncio_Future_set_exception(FutureObj * self,PyObject * exception)470 _asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
471 /*[clinic end generated code: output=f1c1b0cd321be360 input=1377dbe15e6ea186]*/
472 {
473 return future_set_exception(self, exception);
474 }
475
476 /*[clinic input]
477 _asyncio.Future.add_done_callback
478
479 fn: 'O'
480 /
481
482 Add a callback to be run when the future becomes done.
483
484 The callback is called with a single argument - the future object. If
485 the future is already done when this is called, the callback is
486 scheduled with call_soon.
487 [clinic start generated code]*/
488
489 static PyObject *
_asyncio_Future_add_done_callback(FutureObj * self,PyObject * fn)490 _asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
491 /*[clinic end generated code: output=819e09629b2ec2b5 input=8cce187e32cec6a8]*/
492 {
493 return future_add_done_callback(self, fn);
494 }
495
496 /*[clinic input]
497 _asyncio.Future.remove_done_callback
498
499 fn: 'O'
500 /
501
502 Remove all instances of a callback from the "call when done" list.
503
504 Returns the number of callbacks removed.
505 [clinic start generated code]*/
506
507 static PyObject *
_asyncio_Future_remove_done_callback(FutureObj * self,PyObject * fn)508 _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
509 /*[clinic end generated code: output=5ab1fb52b24ef31f input=3fedb73e1409c31c]*/
510 {
511 PyObject *newlist;
512 Py_ssize_t len, i, j=0;
513
514 len = PyList_GET_SIZE(self->fut_callbacks);
515 if (len == 0) {
516 return PyLong_FromSsize_t(0);
517 }
518
519 newlist = PyList_New(len);
520 if (newlist == NULL) {
521 return NULL;
522 }
523
524 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
525 int ret;
526 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
527
528 if ((ret = PyObject_RichCompareBool(fn, item, Py_EQ)) < 0) {
529 goto fail;
530 }
531 if (ret == 0) {
532 Py_INCREF(item);
533 PyList_SET_ITEM(newlist, j, item);
534 j++;
535 }
536 }
537
538 if (PyList_SetSlice(newlist, j, len, NULL) < 0) {
539 goto fail;
540 }
541 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
542 goto fail;
543 }
544 Py_DECREF(newlist);
545 return PyLong_FromSsize_t(len - j);
546
547 fail:
548 Py_DECREF(newlist);
549 return NULL;
550 }
551
552 /*[clinic input]
553 _asyncio.Future.cancel
554
555 Cancel the future and schedule callbacks.
556
557 If the future is already done or cancelled, return False. Otherwise,
558 change the future's state to cancelled, schedule the callbacks and
559 return True.
560 [clinic start generated code]*/
561
562 static PyObject *
_asyncio_Future_cancel_impl(FutureObj * self)563 _asyncio_Future_cancel_impl(FutureObj *self)
564 /*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
565 {
566 return future_cancel(self);
567 }
568
569 /*[clinic input]
570 _asyncio.Future.cancelled
571
572 Return True if the future was cancelled.
573 [clinic start generated code]*/
574
575 static PyObject *
_asyncio_Future_cancelled_impl(FutureObj * self)576 _asyncio_Future_cancelled_impl(FutureObj *self)
577 /*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
578 {
579 if (self->fut_state == STATE_CANCELLED) {
580 Py_RETURN_TRUE;
581 }
582 else {
583 Py_RETURN_FALSE;
584 }
585 }
586
587 /*[clinic input]
588 _asyncio.Future.done
589
590 Return True if the future is done.
591
592 Done means either that a result / exception are available, or that the
593 future was cancelled.
594 [clinic start generated code]*/
595
596 static PyObject *
_asyncio_Future_done_impl(FutureObj * self)597 _asyncio_Future_done_impl(FutureObj *self)
598 /*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
599 {
600 if (self->fut_state == STATE_PENDING) {
601 Py_RETURN_FALSE;
602 }
603 else {
604 Py_RETURN_TRUE;
605 }
606 }
607
608 static PyObject *
FutureObj_get_blocking(FutureObj * fut)609 FutureObj_get_blocking(FutureObj *fut)
610 {
611 if (fut->fut_blocking) {
612 Py_RETURN_TRUE;
613 }
614 else {
615 Py_RETURN_FALSE;
616 }
617 }
618
619 static int
FutureObj_set_blocking(FutureObj * fut,PyObject * val)620 FutureObj_set_blocking(FutureObj *fut, PyObject *val)
621 {
622 int is_true = PyObject_IsTrue(val);
623 if (is_true < 0) {
624 return -1;
625 }
626 fut->fut_blocking = is_true;
627 return 0;
628 }
629
630 static PyObject *
FutureObj_get_log_traceback(FutureObj * fut)631 FutureObj_get_log_traceback(FutureObj *fut)
632 {
633 if (fut->fut_log_tb) {
634 Py_RETURN_TRUE;
635 }
636 else {
637 Py_RETURN_FALSE;
638 }
639 }
640
641 static PyObject *
FutureObj_get_loop(FutureObj * fut)642 FutureObj_get_loop(FutureObj *fut)
643 {
644 if (fut->fut_loop == NULL) {
645 Py_RETURN_NONE;
646 }
647 Py_INCREF(fut->fut_loop);
648 return fut->fut_loop;
649 }
650
651 static PyObject *
FutureObj_get_callbacks(FutureObj * fut)652 FutureObj_get_callbacks(FutureObj *fut)
653 {
654 if (fut->fut_callbacks == NULL) {
655 Py_RETURN_NONE;
656 }
657 Py_INCREF(fut->fut_callbacks);
658 return fut->fut_callbacks;
659 }
660
661 static PyObject *
FutureObj_get_result(FutureObj * fut)662 FutureObj_get_result(FutureObj *fut)
663 {
664 if (fut->fut_result == NULL) {
665 Py_RETURN_NONE;
666 }
667 Py_INCREF(fut->fut_result);
668 return fut->fut_result;
669 }
670
671 static PyObject *
FutureObj_get_exception(FutureObj * fut)672 FutureObj_get_exception(FutureObj *fut)
673 {
674 if (fut->fut_exception == NULL) {
675 Py_RETURN_NONE;
676 }
677 Py_INCREF(fut->fut_exception);
678 return fut->fut_exception;
679 }
680
681 static PyObject *
FutureObj_get_source_traceback(FutureObj * fut)682 FutureObj_get_source_traceback(FutureObj *fut)
683 {
684 if (fut->fut_source_tb == NULL) {
685 Py_RETURN_NONE;
686 }
687 Py_INCREF(fut->fut_source_tb);
688 return fut->fut_source_tb;
689 }
690
691 static PyObject *
FutureObj_get_state(FutureObj * fut)692 FutureObj_get_state(FutureObj *fut)
693 {
694 _Py_IDENTIFIER(PENDING);
695 _Py_IDENTIFIER(CANCELLED);
696 _Py_IDENTIFIER(FINISHED);
697 PyObject *ret = NULL;
698
699 switch (fut->fut_state) {
700 case STATE_PENDING:
701 ret = _PyUnicode_FromId(&PyId_PENDING);
702 break;
703 case STATE_CANCELLED:
704 ret = _PyUnicode_FromId(&PyId_CANCELLED);
705 break;
706 case STATE_FINISHED:
707 ret = _PyUnicode_FromId(&PyId_FINISHED);
708 break;
709 default:
710 assert (0);
711 }
712 Py_INCREF(ret);
713 return ret;
714 }
715
716 /*[clinic input]
717 _asyncio.Future._repr_info
718 [clinic start generated code]*/
719
720 static PyObject *
_asyncio_Future__repr_info_impl(FutureObj * self)721 _asyncio_Future__repr_info_impl(FutureObj *self)
722 /*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
723 {
724 return PyObject_CallFunctionObjArgs(
725 asyncio_future_repr_info_func, self, NULL);
726 }
727
728 /*[clinic input]
729 _asyncio.Future._schedule_callbacks
730 [clinic start generated code]*/
731
732 static PyObject *
_asyncio_Future__schedule_callbacks_impl(FutureObj * self)733 _asyncio_Future__schedule_callbacks_impl(FutureObj *self)
734 /*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/
735 {
736 int ret = future_schedule_callbacks(self);
737 if (ret == -1) {
738 return NULL;
739 }
740 Py_RETURN_NONE;
741 }
742
743 static PyObject *
FutureObj_repr(FutureObj * fut)744 FutureObj_repr(FutureObj *fut)
745 {
746 _Py_IDENTIFIER(_repr_info);
747
748 PyObject *_repr_info = _PyUnicode_FromId(&PyId__repr_info); // borrowed
749 if (_repr_info == NULL) {
750 return NULL;
751 }
752
753 PyObject *rinfo = PyObject_CallMethodObjArgs((PyObject*)fut, _repr_info,
754 NULL);
755 if (rinfo == NULL) {
756 return NULL;
757 }
758
759 PyObject *sp = PyUnicode_FromString(" ");
760 if (sp == NULL) {
761 Py_DECREF(rinfo);
762 return NULL;
763 }
764
765 PyObject *rinfo_s = PyUnicode_Join(sp, rinfo);
766 Py_DECREF(sp);
767 Py_DECREF(rinfo);
768 if (rinfo_s == NULL) {
769 return NULL;
770 }
771
772 PyObject *rstr = NULL;
773 PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
774 "__name__");
775 if (type_name != NULL) {
776 rstr = PyUnicode_FromFormat("<%S %S>", type_name, rinfo_s);
777 Py_DECREF(type_name);
778 }
779 Py_DECREF(rinfo_s);
780 return rstr;
781 }
782
783 static void
FutureObj_finalize(FutureObj * fut)784 FutureObj_finalize(FutureObj *fut)
785 {
786 _Py_IDENTIFIER(call_exception_handler);
787 _Py_IDENTIFIER(message);
788 _Py_IDENTIFIER(exception);
789 _Py_IDENTIFIER(future);
790 _Py_IDENTIFIER(source_traceback);
791
792 if (!fut->fut_log_tb) {
793 return;
794 }
795 assert(fut->fut_exception != NULL);
796 fut->fut_log_tb = 0;;
797
798 PyObject *error_type, *error_value, *error_traceback;
799 /* Save the current exception, if any. */
800 PyErr_Fetch(&error_type, &error_value, &error_traceback);
801
802 PyObject *context = NULL;
803 PyObject *type_name = NULL;
804 PyObject *message = NULL;
805 PyObject *func = NULL;
806 PyObject *res = NULL;
807
808 context = PyDict_New();
809 if (context == NULL) {
810 goto finally;
811 }
812
813 type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
814 if (type_name == NULL) {
815 goto finally;
816 }
817
818 message = PyUnicode_FromFormat(
819 "%S exception was never retrieved", type_name);
820 if (message == NULL) {
821 goto finally;
822 }
823
824 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
825 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
826 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
827 goto finally;
828 }
829 if (fut->fut_source_tb != NULL) {
830 if (_PyDict_SetItemId(context, &PyId_source_traceback,
831 fut->fut_source_tb) < 0) {
832 goto finally;
833 }
834 }
835
836 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
837 if (func != NULL) {
838 res = _PyObject_CallArg1(func, context);
839 if (res == NULL) {
840 PyErr_WriteUnraisable(func);
841 }
842 }
843
844 finally:
845 Py_CLEAR(context);
846 Py_CLEAR(type_name);
847 Py_CLEAR(message);
848 Py_CLEAR(func);
849 Py_CLEAR(res);
850
851 /* Restore the saved exception. */
852 PyErr_Restore(error_type, error_value, error_traceback);
853 }
854
855
856 static PyAsyncMethods FutureType_as_async = {
857 (unaryfunc)future_new_iter, /* am_await */
858 0, /* am_aiter */
859 0 /* am_anext */
860 };
861
862 static PyMethodDef FutureType_methods[] = {
863 _ASYNCIO_FUTURE_RESULT_METHODDEF
864 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
865 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
866 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
867 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
868 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
869 _ASYNCIO_FUTURE_CANCEL_METHODDEF
870 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
871 _ASYNCIO_FUTURE_DONE_METHODDEF
872 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
873 _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF
874 {NULL, NULL} /* Sentinel */
875 };
876
877 #define FUTURE_COMMON_GETSETLIST \
878 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
879 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
880 (setter)FutureObj_set_blocking, NULL}, \
881 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
882 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
883 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
884 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
885 {"_log_traceback", (getter)FutureObj_get_log_traceback, NULL, NULL}, \
886 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
887
888 static PyGetSetDef FutureType_getsetlist[] = {
889 FUTURE_COMMON_GETSETLIST
890 {NULL} /* Sentinel */
891 };
892
893 static void FutureObj_dealloc(PyObject *self);
894
895 static PyTypeObject FutureType = {
896 PyVarObject_HEAD_INIT(NULL, 0)
897 "_asyncio.Future",
898 sizeof(FutureObj), /* tp_basicsize */
899 .tp_dealloc = FutureObj_dealloc,
900 .tp_as_async = &FutureType_as_async,
901 .tp_repr = (reprfunc)FutureObj_repr,
902 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
903 | Py_TPFLAGS_HAVE_FINALIZE,
904 .tp_doc = _asyncio_Future___init____doc__,
905 .tp_traverse = (traverseproc)FutureObj_traverse,
906 .tp_clear = (inquiry)FutureObj_clear,
907 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
908 .tp_iter = (getiterfunc)future_new_iter,
909 .tp_methods = FutureType_methods,
910 .tp_getset = FutureType_getsetlist,
911 .tp_dictoffset = offsetof(FutureObj, dict),
912 .tp_init = (initproc)_asyncio_Future___init__,
913 .tp_new = PyType_GenericNew,
914 .tp_finalize = (destructor)FutureObj_finalize,
915 };
916
917 #define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
918
919 static inline int
future_call_schedule_callbacks(FutureObj * fut)920 future_call_schedule_callbacks(FutureObj *fut)
921 {
922 if (Future_CheckExact(fut)) {
923 return future_schedule_callbacks(fut);
924 }
925 else {
926 /* `fut` is a subclass of Future */
927 PyObject *ret = _PyObject_CallMethodId(
928 (PyObject*)fut, &PyId__schedule_callbacks, NULL);
929 if (ret == NULL) {
930 return -1;
931 }
932
933 Py_DECREF(ret);
934 return 0;
935 }
936 }
937
938 static void
FutureObj_dealloc(PyObject * self)939 FutureObj_dealloc(PyObject *self)
940 {
941 FutureObj *fut = (FutureObj *)self;
942
943 if (Future_CheckExact(fut)) {
944 /* When fut is subclass of Future, finalizer is called from
945 * subtype_dealloc.
946 */
947 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
948 // resurrected.
949 return;
950 }
951 }
952
953 if (fut->fut_weakreflist != NULL) {
954 PyObject_ClearWeakRefs(self);
955 }
956
957 (void)FutureObj_clear(fut);
958 Py_TYPE(fut)->tp_free(fut);
959 }
960
961
962 /*********************** Future Iterator **************************/
963
964 typedef struct {
965 PyObject_HEAD
966 FutureObj *future;
967 } futureiterobject;
968
969 static void
FutureIter_dealloc(futureiterobject * it)970 FutureIter_dealloc(futureiterobject *it)
971 {
972 PyObject_GC_UnTrack(it);
973 Py_XDECREF(it->future);
974 PyObject_GC_Del(it);
975 }
976
977 static PyObject *
FutureIter_iternext(futureiterobject * it)978 FutureIter_iternext(futureiterobject *it)
979 {
980 PyObject *res;
981 FutureObj *fut = it->future;
982
983 if (fut == NULL) {
984 return NULL;
985 }
986
987 if (fut->fut_state == STATE_PENDING) {
988 if (!fut->fut_blocking) {
989 fut->fut_blocking = 1;
990 Py_INCREF(fut);
991 return (PyObject *)fut;
992 }
993 PyErr_Format(PyExc_AssertionError,
994 "yield from wasn't used with future");
995 return NULL;
996 }
997
998 res = _asyncio_Future_result_impl(fut);
999 if (res != NULL) {
1000 /* The result of the Future is not an exception. */
1001 if (_PyGen_SetStopIterationValue(res) < 0) {
1002 Py_DECREF(res);
1003 return NULL;
1004 }
1005 Py_DECREF(res);
1006 }
1007
1008 it->future = NULL;
1009 Py_DECREF(fut);
1010 return NULL;
1011 }
1012
1013 static PyObject *
FutureIter_send(futureiterobject * self,PyObject * unused)1014 FutureIter_send(futureiterobject *self, PyObject *unused)
1015 {
1016 /* Future.__iter__ doesn't care about values that are pushed to the
1017 * generator, it just returns "self.result().
1018 */
1019 return FutureIter_iternext(self);
1020 }
1021
1022 static PyObject *
FutureIter_throw(futureiterobject * self,PyObject * args)1023 FutureIter_throw(futureiterobject *self, PyObject *args)
1024 {
1025 PyObject *type=NULL, *val=NULL, *tb=NULL;
1026 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1027 return NULL;
1028
1029 if (val == Py_None) {
1030 val = NULL;
1031 }
1032 if (tb == Py_None) {
1033 tb = NULL;
1034 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1035 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1036 return NULL;
1037 }
1038
1039 Py_INCREF(type);
1040 Py_XINCREF(val);
1041 Py_XINCREF(tb);
1042
1043 if (PyExceptionClass_Check(type)) {
1044 PyErr_NormalizeException(&type, &val, &tb);
1045 /* No need to call PyException_SetTraceback since we'll be calling
1046 PyErr_Restore for `type`, `val`, and `tb`. */
1047 } else if (PyExceptionInstance_Check(type)) {
1048 if (val) {
1049 PyErr_SetString(PyExc_TypeError,
1050 "instance exception may not have a separate value");
1051 goto fail;
1052 }
1053 val = type;
1054 type = PyExceptionInstance_Class(type);
1055 Py_INCREF(type);
1056 if (tb == NULL)
1057 tb = PyException_GetTraceback(val);
1058 } else {
1059 PyErr_SetString(PyExc_TypeError,
1060 "exceptions must be classes deriving BaseException or "
1061 "instances of such a class");
1062 goto fail;
1063 }
1064
1065 Py_CLEAR(self->future);
1066
1067 PyErr_Restore(type, val, tb);
1068
1069 return FutureIter_iternext(self);
1070
1071 fail:
1072 Py_DECREF(type);
1073 Py_XDECREF(val);
1074 Py_XDECREF(tb);
1075 return NULL;
1076 }
1077
1078 static PyObject *
FutureIter_close(futureiterobject * self,PyObject * arg)1079 FutureIter_close(futureiterobject *self, PyObject *arg)
1080 {
1081 Py_CLEAR(self->future);
1082 Py_RETURN_NONE;
1083 }
1084
1085 static int
FutureIter_traverse(futureiterobject * it,visitproc visit,void * arg)1086 FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1087 {
1088 Py_VISIT(it->future);
1089 return 0;
1090 }
1091
1092 static PyMethodDef FutureIter_methods[] = {
1093 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1094 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1095 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1096 {NULL, NULL} /* Sentinel */
1097 };
1098
1099 static PyTypeObject FutureIterType = {
1100 PyVarObject_HEAD_INIT(NULL, 0)
1101 "_asyncio.FutureIter",
1102 .tp_basicsize = sizeof(futureiterobject),
1103 .tp_itemsize = 0,
1104 .tp_dealloc = (destructor)FutureIter_dealloc,
1105 .tp_getattro = PyObject_GenericGetAttr,
1106 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1107 .tp_traverse = (traverseproc)FutureIter_traverse,
1108 .tp_iter = PyObject_SelfIter,
1109 .tp_iternext = (iternextfunc)FutureIter_iternext,
1110 .tp_methods = FutureIter_methods,
1111 };
1112
1113 static PyObject *
future_new_iter(PyObject * fut)1114 future_new_iter(PyObject *fut)
1115 {
1116 futureiterobject *it;
1117
1118 if (!PyObject_TypeCheck(fut, &FutureType)) {
1119 PyErr_BadInternalCall();
1120 return NULL;
1121 }
1122 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1123 if (it == NULL) {
1124 return NULL;
1125 }
1126 Py_INCREF(fut);
1127 it->future = (FutureObj*)fut;
1128 PyObject_GC_Track(it);
1129 return (PyObject*)it;
1130 }
1131
1132
1133 /*********************** Task **************************/
1134
1135
1136 /*[clinic input]
1137 class _asyncio.Task "TaskObj *" "&Task_Type"
1138 [clinic start generated code]*/
1139 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1140
1141 static int task_call_step_soon(TaskObj *, PyObject *);
1142 static inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
1143 static inline PyObject * task_call_step(TaskObj *, PyObject *);
1144 static PyObject * task_wakeup(TaskObj *, PyObject *);
1145 static PyObject * task_step(TaskObj *, PyObject *);
1146
1147 /* ----- Task._step wrapper */
1148
1149 static int
TaskSendMethWrapper_clear(TaskSendMethWrapper * o)1150 TaskSendMethWrapper_clear(TaskSendMethWrapper *o)
1151 {
1152 Py_CLEAR(o->sw_task);
1153 Py_CLEAR(o->sw_arg);
1154 return 0;
1155 }
1156
1157 static void
TaskSendMethWrapper_dealloc(TaskSendMethWrapper * o)1158 TaskSendMethWrapper_dealloc(TaskSendMethWrapper *o)
1159 {
1160 PyObject_GC_UnTrack(o);
1161 (void)TaskSendMethWrapper_clear(o);
1162 Py_TYPE(o)->tp_free(o);
1163 }
1164
1165 static PyObject *
TaskSendMethWrapper_call(TaskSendMethWrapper * o,PyObject * args,PyObject * kwds)1166 TaskSendMethWrapper_call(TaskSendMethWrapper *o,
1167 PyObject *args, PyObject *kwds)
1168 {
1169 return task_call_step(o->sw_task, o->sw_arg);
1170 }
1171
1172 static int
TaskSendMethWrapper_traverse(TaskSendMethWrapper * o,visitproc visit,void * arg)1173 TaskSendMethWrapper_traverse(TaskSendMethWrapper *o,
1174 visitproc visit, void *arg)
1175 {
1176 Py_VISIT(o->sw_task);
1177 Py_VISIT(o->sw_arg);
1178 return 0;
1179 }
1180
1181 static PyObject *
TaskSendMethWrapper_get___self__(TaskSendMethWrapper * o)1182 TaskSendMethWrapper_get___self__(TaskSendMethWrapper *o)
1183 {
1184 if (o->sw_task) {
1185 Py_INCREF(o->sw_task);
1186 return (PyObject*)o->sw_task;
1187 }
1188 Py_RETURN_NONE;
1189 }
1190
1191 static PyGetSetDef TaskSendMethWrapper_getsetlist[] = {
1192 {"__self__", (getter)TaskSendMethWrapper_get___self__, NULL, NULL},
1193 {NULL} /* Sentinel */
1194 };
1195
1196 PyTypeObject TaskSendMethWrapper_Type = {
1197 PyVarObject_HEAD_INIT(NULL, 0)
1198 "TaskSendMethWrapper",
1199 .tp_basicsize = sizeof(TaskSendMethWrapper),
1200 .tp_itemsize = 0,
1201 .tp_getset = TaskSendMethWrapper_getsetlist,
1202 .tp_dealloc = (destructor)TaskSendMethWrapper_dealloc,
1203 .tp_call = (ternaryfunc)TaskSendMethWrapper_call,
1204 .tp_getattro = PyObject_GenericGetAttr,
1205 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1206 .tp_traverse = (traverseproc)TaskSendMethWrapper_traverse,
1207 .tp_clear = (inquiry)TaskSendMethWrapper_clear,
1208 };
1209
1210 static PyObject *
TaskSendMethWrapper_new(TaskObj * task,PyObject * arg)1211 TaskSendMethWrapper_new(TaskObj *task, PyObject *arg)
1212 {
1213 TaskSendMethWrapper *o;
1214 o = PyObject_GC_New(TaskSendMethWrapper, &TaskSendMethWrapper_Type);
1215 if (o == NULL) {
1216 return NULL;
1217 }
1218
1219 Py_INCREF(task);
1220 o->sw_task = task;
1221
1222 Py_XINCREF(arg);
1223 o->sw_arg = arg;
1224
1225 PyObject_GC_Track(o);
1226 return (PyObject*) o;
1227 }
1228
1229 /* ----- Task._wakeup wrapper */
1230
1231 static PyObject *
TaskWakeupMethWrapper_call(TaskWakeupMethWrapper * o,PyObject * args,PyObject * kwds)1232 TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1233 PyObject *args, PyObject *kwds)
1234 {
1235 PyObject *fut;
1236
1237 if (!PyArg_ParseTuple(args, "O|", &fut)) {
1238 return NULL;
1239 }
1240
1241 return task_call_wakeup(o->ww_task, fut);
1242 }
1243
1244 static int
TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper * o)1245 TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1246 {
1247 Py_CLEAR(o->ww_task);
1248 return 0;
1249 }
1250
1251 static int
TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper * o,visitproc visit,void * arg)1252 TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1253 visitproc visit, void *arg)
1254 {
1255 Py_VISIT(o->ww_task);
1256 return 0;
1257 }
1258
1259 static void
TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper * o)1260 TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1261 {
1262 PyObject_GC_UnTrack(o);
1263 (void)TaskWakeupMethWrapper_clear(o);
1264 Py_TYPE(o)->tp_free(o);
1265 }
1266
1267 PyTypeObject TaskWakeupMethWrapper_Type = {
1268 PyVarObject_HEAD_INIT(NULL, 0)
1269 "TaskWakeupMethWrapper",
1270 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1271 .tp_itemsize = 0,
1272 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1273 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1274 .tp_getattro = PyObject_GenericGetAttr,
1275 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1276 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1277 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1278 };
1279
1280 static PyObject *
TaskWakeupMethWrapper_new(TaskObj * task)1281 TaskWakeupMethWrapper_new(TaskObj *task)
1282 {
1283 TaskWakeupMethWrapper *o;
1284 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1285 if (o == NULL) {
1286 return NULL;
1287 }
1288
1289 Py_INCREF(task);
1290 o->ww_task = task;
1291
1292 PyObject_GC_Track(o);
1293 return (PyObject*) o;
1294 }
1295
1296 /* ----- Task */
1297
1298 /*[clinic input]
1299 _asyncio.Task.__init__
1300
1301 coro: 'O'
1302 *
1303 loop: 'O' = NULL
1304
1305 A coroutine wrapped in a Future.
1306 [clinic start generated code]*/
1307
1308 static int
_asyncio_Task___init___impl(TaskObj * self,PyObject * coro,PyObject * loop)1309 _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
1310 /*[clinic end generated code: output=9f24774c2287fc2f input=71d8d28c201a18cd]*/
1311 {
1312 PyObject *res;
1313 _Py_IDENTIFIER(add);
1314
1315 if (future_init((FutureObj*)self, loop)) {
1316 return -1;
1317 }
1318
1319 self->task_fut_waiter = NULL;
1320 self->task_must_cancel = 0;
1321 self->task_log_destroy_pending = 1;
1322
1323 Py_INCREF(coro);
1324 self->task_coro = coro;
1325
1326 if (task_call_step_soon(self, NULL)) {
1327 return -1;
1328 }
1329
1330 res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_add, self, NULL);
1331 if (res == NULL) {
1332 return -1;
1333 }
1334 Py_DECREF(res);
1335
1336 return 0;
1337 }
1338
1339 static int
TaskObj_clear(TaskObj * task)1340 TaskObj_clear(TaskObj *task)
1341 {
1342 (void)FutureObj_clear((FutureObj*) task);
1343 Py_CLEAR(task->task_coro);
1344 Py_CLEAR(task->task_fut_waiter);
1345 return 0;
1346 }
1347
1348 static int
TaskObj_traverse(TaskObj * task,visitproc visit,void * arg)1349 TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1350 {
1351 Py_VISIT(task->task_coro);
1352 Py_VISIT(task->task_fut_waiter);
1353 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1354 return 0;
1355 }
1356
1357 static PyObject *
TaskObj_get_log_destroy_pending(TaskObj * task)1358 TaskObj_get_log_destroy_pending(TaskObj *task)
1359 {
1360 if (task->task_log_destroy_pending) {
1361 Py_RETURN_TRUE;
1362 }
1363 else {
1364 Py_RETURN_FALSE;
1365 }
1366 }
1367
1368 static int
TaskObj_set_log_destroy_pending(TaskObj * task,PyObject * val)1369 TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1370 {
1371 int is_true = PyObject_IsTrue(val);
1372 if (is_true < 0) {
1373 return -1;
1374 }
1375 task->task_log_destroy_pending = is_true;
1376 return 0;
1377 }
1378
1379 static PyObject *
TaskObj_get_must_cancel(TaskObj * task)1380 TaskObj_get_must_cancel(TaskObj *task)
1381 {
1382 if (task->task_must_cancel) {
1383 Py_RETURN_TRUE;
1384 }
1385 else {
1386 Py_RETURN_FALSE;
1387 }
1388 }
1389
1390 static PyObject *
TaskObj_get_coro(TaskObj * task)1391 TaskObj_get_coro(TaskObj *task)
1392 {
1393 if (task->task_coro) {
1394 Py_INCREF(task->task_coro);
1395 return task->task_coro;
1396 }
1397
1398 Py_RETURN_NONE;
1399 }
1400
1401 static PyObject *
TaskObj_get_fut_waiter(TaskObj * task)1402 TaskObj_get_fut_waiter(TaskObj *task)
1403 {
1404 if (task->task_fut_waiter) {
1405 Py_INCREF(task->task_fut_waiter);
1406 return task->task_fut_waiter;
1407 }
1408
1409 Py_RETURN_NONE;
1410 }
1411
1412 /*[clinic input]
1413 @classmethod
1414 _asyncio.Task.current_task
1415
1416 loop: 'O' = None
1417
1418 Return the currently running task in an event loop or None.
1419
1420 By default the current task for the current event loop is returned.
1421
1422 None is returned when called not in the context of a Task.
1423 [clinic start generated code]*/
1424
1425 static PyObject *
_asyncio_Task_current_task_impl(PyTypeObject * type,PyObject * loop)1426 _asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
1427 /*[clinic end generated code: output=99fbe7332c516e03 input=a0d6cdf2e3b243e1]*/
1428 {
1429 PyObject *res;
1430
1431 if (loop == Py_None) {
1432 loop = _PyObject_CallNoArg(asyncio_get_event_loop);
1433 if (loop == NULL) {
1434 return NULL;
1435 }
1436
1437 res = PyDict_GetItem(current_tasks, loop);
1438 Py_DECREF(loop);
1439 }
1440 else {
1441 res = PyDict_GetItem(current_tasks, loop);
1442 }
1443
1444 if (res == NULL) {
1445 Py_RETURN_NONE;
1446 }
1447 else {
1448 Py_INCREF(res);
1449 return res;
1450 }
1451 }
1452
1453 static PyObject *
task_all_tasks(PyObject * loop)1454 task_all_tasks(PyObject *loop)
1455 {
1456 PyObject *task;
1457 PyObject *task_loop;
1458 PyObject *set;
1459 PyObject *iter;
1460
1461 assert(loop != NULL);
1462
1463 set = PySet_New(NULL);
1464 if (set == NULL) {
1465 return NULL;
1466 }
1467
1468 iter = PyObject_GetIter(all_tasks);
1469 if (iter == NULL) {
1470 goto fail;
1471 }
1472
1473 while ((task = PyIter_Next(iter))) {
1474 task_loop = PyObject_GetAttrString(task, "_loop");
1475 if (task_loop == NULL) {
1476 Py_DECREF(task);
1477 goto fail;
1478 }
1479 if (task_loop == loop) {
1480 if (PySet_Add(set, task) == -1) {
1481 Py_DECREF(task_loop);
1482 Py_DECREF(task);
1483 goto fail;
1484 }
1485 }
1486 Py_DECREF(task_loop);
1487 Py_DECREF(task);
1488 }
1489
1490 Py_DECREF(iter);
1491 return set;
1492
1493 fail:
1494 Py_XDECREF(set);
1495 Py_XDECREF(iter);
1496 return NULL;
1497 }
1498
1499 /*[clinic input]
1500 @classmethod
1501 _asyncio.Task.all_tasks
1502
1503 loop: 'O' = None
1504
1505 Return a set of all tasks for an event loop.
1506
1507 By default all tasks for the current event loop are returned.
1508 [clinic start generated code]*/
1509
1510 static PyObject *
_asyncio_Task_all_tasks_impl(PyTypeObject * type,PyObject * loop)1511 _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
1512 /*[clinic end generated code: output=11f9b20749ccca5d input=c6f5b53bd487488f]*/
1513 {
1514 PyObject *res;
1515
1516 if (loop == Py_None) {
1517 loop = _PyObject_CallNoArg(asyncio_get_event_loop);
1518 if (loop == NULL) {
1519 return NULL;
1520 }
1521
1522 res = task_all_tasks(loop);
1523 Py_DECREF(loop);
1524 }
1525 else {
1526 res = task_all_tasks(loop);
1527 }
1528
1529 return res;
1530 }
1531
1532 /*[clinic input]
1533 _asyncio.Task._repr_info
1534 [clinic start generated code]*/
1535
1536 static PyObject *
_asyncio_Task__repr_info_impl(TaskObj * self)1537 _asyncio_Task__repr_info_impl(TaskObj *self)
1538 /*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
1539 {
1540 return PyObject_CallFunctionObjArgs(
1541 asyncio_task_repr_info_func, self, NULL);
1542 }
1543
1544 /*[clinic input]
1545 _asyncio.Task.cancel
1546
1547 Request that this task cancel itself.
1548
1549 This arranges for a CancelledError to be thrown into the
1550 wrapped coroutine on the next cycle through the event loop.
1551 The coroutine then has a chance to clean up or even deny
1552 the request using try/except/finally.
1553
1554 Unlike Future.cancel, this does not guarantee that the
1555 task will be cancelled: the exception might be caught and
1556 acted upon, delaying cancellation of the task or preventing
1557 cancellation completely. The task may also return a value or
1558 raise a different exception.
1559
1560 Immediately after this method is called, Task.cancelled() will
1561 not return True (unless the task was already cancelled). A
1562 task will be marked as cancelled when the wrapped coroutine
1563 terminates with a CancelledError exception (even if cancel()
1564 was not called).
1565 [clinic start generated code]*/
1566
1567 static PyObject *
_asyncio_Task_cancel_impl(TaskObj * self)1568 _asyncio_Task_cancel_impl(TaskObj *self)
1569 /*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
1570 {
1571 if (self->task_state != STATE_PENDING) {
1572 Py_RETURN_FALSE;
1573 }
1574
1575 if (self->task_fut_waiter) {
1576 PyObject *res;
1577 int is_true;
1578
1579 res = _PyObject_CallMethodId(
1580 self->task_fut_waiter, &PyId_cancel, NULL);
1581 if (res == NULL) {
1582 return NULL;
1583 }
1584
1585 is_true = PyObject_IsTrue(res);
1586 Py_DECREF(res);
1587 if (is_true < 0) {
1588 return NULL;
1589 }
1590
1591 if (is_true) {
1592 Py_RETURN_TRUE;
1593 }
1594 }
1595
1596 self->task_must_cancel = 1;
1597 Py_RETURN_TRUE;
1598 }
1599
1600 /*[clinic input]
1601 _asyncio.Task.get_stack
1602
1603 *
1604 limit: 'O' = None
1605
1606 Return the list of stack frames for this task's coroutine.
1607
1608 If the coroutine is not done, this returns the stack where it is
1609 suspended. If the coroutine has completed successfully or was
1610 cancelled, this returns an empty list. If the coroutine was
1611 terminated by an exception, this returns the list of traceback
1612 frames.
1613
1614 The frames are always ordered from oldest to newest.
1615
1616 The optional limit gives the maximum number of frames to
1617 return; by default all available frames are returned. Its
1618 meaning differs depending on whether a stack or a traceback is
1619 returned: the newest frames of a stack are returned, but the
1620 oldest frames of a traceback are returned. (This matches the
1621 behavior of the traceback module.)
1622
1623 For reasons beyond our control, only one stack frame is
1624 returned for a suspended coroutine.
1625 [clinic start generated code]*/
1626
1627 static PyObject *
_asyncio_Task_get_stack_impl(TaskObj * self,PyObject * limit)1628 _asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
1629 /*[clinic end generated code: output=c9aeeeebd1e18118 input=b1920230a766d17a]*/
1630 {
1631 return PyObject_CallFunctionObjArgs(
1632 asyncio_task_get_stack_func, self, limit, NULL);
1633 }
1634
1635 /*[clinic input]
1636 _asyncio.Task.print_stack
1637
1638 *
1639 limit: 'O' = None
1640 file: 'O' = None
1641
1642 Print the stack or traceback for this task's coroutine.
1643
1644 This produces output similar to that of the traceback module,
1645 for the frames retrieved by get_stack(). The limit argument
1646 is passed to get_stack(). The file argument is an I/O stream
1647 to which the output is written; by default output is written
1648 to sys.stderr.
1649 [clinic start generated code]*/
1650
1651 static PyObject *
_asyncio_Task_print_stack_impl(TaskObj * self,PyObject * limit,PyObject * file)1652 _asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
1653 PyObject *file)
1654 /*[clinic end generated code: output=7339e10314cd3f4d input=19f1e99ab5400bc3]*/
1655 {
1656 return PyObject_CallFunctionObjArgs(
1657 asyncio_task_print_stack_func, self, limit, file, NULL);
1658 }
1659
1660 /*[clinic input]
1661 _asyncio.Task._step
1662
1663 exc: 'O' = NULL
1664 [clinic start generated code]*/
1665
1666 static PyObject *
_asyncio_Task__step_impl(TaskObj * self,PyObject * exc)1667 _asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
1668 /*[clinic end generated code: output=7ed23f0cefd5ae42 input=ada4b2324e5370af]*/
1669 {
1670 return task_step(self, exc == Py_None ? NULL : exc);
1671 }
1672
1673 /*[clinic input]
1674 _asyncio.Task._wakeup
1675
1676 fut: 'O'
1677 [clinic start generated code]*/
1678
1679 static PyObject *
_asyncio_Task__wakeup_impl(TaskObj * self,PyObject * fut)1680 _asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
1681 /*[clinic end generated code: output=75cb341c760fd071 input=11ee4918a5bdbf21]*/
1682 {
1683 return task_wakeup(self, fut);
1684 }
1685
1686 static void
TaskObj_finalize(TaskObj * task)1687 TaskObj_finalize(TaskObj *task)
1688 {
1689 _Py_IDENTIFIER(call_exception_handler);
1690 _Py_IDENTIFIER(task);
1691 _Py_IDENTIFIER(message);
1692 _Py_IDENTIFIER(source_traceback);
1693
1694 PyObject *message = NULL;
1695 PyObject *context = NULL;
1696 PyObject *func = NULL;
1697 PyObject *res = NULL;
1698
1699 PyObject *error_type, *error_value, *error_traceback;
1700
1701 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
1702 goto done;
1703 }
1704
1705 /* Save the current exception, if any. */
1706 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1707
1708 context = PyDict_New();
1709 if (context == NULL) {
1710 goto finally;
1711 }
1712
1713 message = PyUnicode_FromString("Task was destroyed but it is pending!");
1714 if (message == NULL) {
1715 goto finally;
1716 }
1717
1718 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1719 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
1720 {
1721 goto finally;
1722 }
1723
1724 if (task->task_source_tb != NULL) {
1725 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1726 task->task_source_tb) < 0)
1727 {
1728 goto finally;
1729 }
1730 }
1731
1732 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
1733 if (func != NULL) {
1734 res = _PyObject_CallArg1(func, context);
1735 if (res == NULL) {
1736 PyErr_WriteUnraisable(func);
1737 }
1738 }
1739
1740 finally:
1741 Py_CLEAR(context);
1742 Py_CLEAR(message);
1743 Py_CLEAR(func);
1744 Py_CLEAR(res);
1745
1746 /* Restore the saved exception. */
1747 PyErr_Restore(error_type, error_value, error_traceback);
1748
1749 done:
1750 FutureObj_finalize((FutureObj*)task);
1751 }
1752
1753 static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
1754
1755 static PyMethodDef TaskType_methods[] = {
1756 _ASYNCIO_FUTURE_RESULT_METHODDEF
1757 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1758 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1759 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1760 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1761 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1762 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1763 _ASYNCIO_FUTURE_DONE_METHODDEF
1764 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
1765 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
1766 _ASYNCIO_TASK_CANCEL_METHODDEF
1767 _ASYNCIO_TASK_GET_STACK_METHODDEF
1768 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
1769 _ASYNCIO_TASK__WAKEUP_METHODDEF
1770 _ASYNCIO_TASK__STEP_METHODDEF
1771 _ASYNCIO_TASK__REPR_INFO_METHODDEF
1772 {NULL, NULL} /* Sentinel */
1773 };
1774
1775 static PyGetSetDef TaskType_getsetlist[] = {
1776 FUTURE_COMMON_GETSETLIST
1777 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
1778 (setter)TaskObj_set_log_destroy_pending, NULL},
1779 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
1780 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
1781 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
1782 {NULL} /* Sentinel */
1783 };
1784
1785 static PyTypeObject TaskType = {
1786 PyVarObject_HEAD_INIT(NULL, 0)
1787 "_asyncio.Task",
1788 sizeof(TaskObj), /* tp_basicsize */
1789 .tp_base = &FutureType,
1790 .tp_dealloc = TaskObj_dealloc,
1791 .tp_as_async = &FutureType_as_async,
1792 .tp_repr = (reprfunc)FutureObj_repr,
1793 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1794 | Py_TPFLAGS_HAVE_FINALIZE,
1795 .tp_doc = _asyncio_Task___init____doc__,
1796 .tp_traverse = (traverseproc)TaskObj_traverse,
1797 .tp_clear = (inquiry)TaskObj_clear,
1798 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
1799 .tp_iter = (getiterfunc)future_new_iter,
1800 .tp_methods = TaskType_methods,
1801 .tp_getset = TaskType_getsetlist,
1802 .tp_dictoffset = offsetof(TaskObj, dict),
1803 .tp_init = (initproc)_asyncio_Task___init__,
1804 .tp_new = PyType_GenericNew,
1805 .tp_finalize = (destructor)TaskObj_finalize,
1806 };
1807
1808 #define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
1809
1810 static void
TaskObj_dealloc(PyObject * self)1811 TaskObj_dealloc(PyObject *self)
1812 {
1813 TaskObj *task = (TaskObj *)self;
1814
1815 if (Task_CheckExact(self)) {
1816 /* When fut is subclass of Task, finalizer is called from
1817 * subtype_dealloc.
1818 */
1819 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1820 // resurrected.
1821 return;
1822 }
1823 }
1824
1825 if (task->task_weakreflist != NULL) {
1826 PyObject_ClearWeakRefs(self);
1827 }
1828
1829 (void)TaskObj_clear(task);
1830 Py_TYPE(task)->tp_free(task);
1831 }
1832
1833 static inline PyObject *
task_call_wakeup(TaskObj * task,PyObject * fut)1834 task_call_wakeup(TaskObj *task, PyObject *fut)
1835 {
1836 if (Task_CheckExact(task)) {
1837 return task_wakeup(task, fut);
1838 }
1839 else {
1840 /* `task` is a subclass of Task */
1841 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup,
1842 fut, NULL);
1843 }
1844 }
1845
1846 static inline PyObject *
task_call_step(TaskObj * task,PyObject * arg)1847 task_call_step(TaskObj *task, PyObject *arg)
1848 {
1849 if (Task_CheckExact(task)) {
1850 return task_step(task, arg);
1851 }
1852 else {
1853 /* `task` is a subclass of Task */
1854 if (arg == NULL) {
1855 arg = Py_None;
1856 }
1857 return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
1858 arg, NULL);
1859 }
1860 }
1861
1862 static int
task_call_step_soon(TaskObj * task,PyObject * arg)1863 task_call_step_soon(TaskObj *task, PyObject *arg)
1864 {
1865 PyObject *handle;
1866
1867 PyObject *cb = TaskSendMethWrapper_new(task, arg);
1868 if (cb == NULL) {
1869 return -1;
1870 }
1871
1872 handle = _PyObject_CallMethodIdObjArgs(task->task_loop, &PyId_call_soon,
1873 cb, NULL);
1874 Py_DECREF(cb);
1875 if (handle == NULL) {
1876 return -1;
1877 }
1878
1879 Py_DECREF(handle);
1880 return 0;
1881 }
1882
1883 static PyObject *
task_set_error_soon(TaskObj * task,PyObject * et,const char * format,...)1884 task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
1885 {
1886 PyObject* msg;
1887
1888 va_list vargs;
1889 #ifdef HAVE_STDARG_PROTOTYPES
1890 va_start(vargs, format);
1891 #else
1892 va_start(vargs);
1893 #endif
1894 msg = PyUnicode_FromFormatV(format, vargs);
1895 va_end(vargs);
1896
1897 if (msg == NULL) {
1898 return NULL;
1899 }
1900
1901 PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
1902 Py_DECREF(msg);
1903 if (e == NULL) {
1904 return NULL;
1905 }
1906
1907 if (task_call_step_soon(task, e) == -1) {
1908 Py_DECREF(e);
1909 return NULL;
1910 }
1911
1912 Py_DECREF(e);
1913 Py_RETURN_NONE;
1914 }
1915
1916 static PyObject *
task_step_impl(TaskObj * task,PyObject * exc)1917 task_step_impl(TaskObj *task, PyObject *exc)
1918 {
1919 int res;
1920 int clear_exc = 0;
1921 PyObject *result = NULL;
1922 PyObject *coro = task->task_coro;
1923 PyObject *o;
1924
1925 if (task->task_state != STATE_PENDING) {
1926 PyErr_Format(PyExc_AssertionError,
1927 "_step(): already done: %R %R",
1928 task,
1929 exc ? exc : Py_None);
1930 goto fail;
1931 }
1932
1933 if (task->task_must_cancel) {
1934 assert(exc != Py_None);
1935
1936 if (exc) {
1937 /* Check if exc is a CancelledError */
1938 res = PyObject_IsInstance(exc, asyncio_CancelledError);
1939 if (res == -1) {
1940 /* An error occurred, abort */
1941 goto fail;
1942 }
1943 if (res == 0) {
1944 /* exc is not CancelledError; reset it to NULL */
1945 exc = NULL;
1946 }
1947 }
1948
1949 if (!exc) {
1950 /* exc was not a CancelledError */
1951 exc = PyObject_CallFunctionObjArgs(asyncio_CancelledError, NULL);
1952 if (!exc) {
1953 goto fail;
1954 }
1955 clear_exc = 1;
1956 }
1957
1958 task->task_must_cancel = 0;
1959 }
1960
1961 Py_CLEAR(task->task_fut_waiter);
1962
1963 if (exc == NULL) {
1964 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
1965 result = _PyGen_Send((PyGenObject*)coro, Py_None);
1966 }
1967 else {
1968 result = _PyObject_CallMethodIdObjArgs(
1969 coro, &PyId_send, Py_None, NULL);
1970 }
1971 }
1972 else {
1973 result = _PyObject_CallMethodIdObjArgs(
1974 coro, &PyId_throw, exc, NULL);
1975 if (clear_exc) {
1976 /* We created 'exc' during this call */
1977 Py_CLEAR(exc);
1978 }
1979 }
1980
1981 if (result == NULL) {
1982 PyObject *et, *ev, *tb;
1983
1984 if (_PyGen_FetchStopIterationValue(&o) == 0) {
1985 /* The error is StopIteration and that means that
1986 the underlying coroutine has resolved */
1987 PyObject *res = future_set_result((FutureObj*)task, o);
1988 Py_DECREF(o);
1989 if (res == NULL) {
1990 return NULL;
1991 }
1992 Py_DECREF(res);
1993 Py_RETURN_NONE;
1994 }
1995
1996 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
1997 /* CancelledError */
1998 PyErr_Clear();
1999 return future_cancel((FutureObj*)task);
2000 }
2001
2002 /* Some other exception; pop it and call Task.set_exception() */
2003 PyErr_Fetch(&et, &ev, &tb);
2004 assert(et);
2005 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2006 PyErr_NormalizeException(&et, &ev, &tb);
2007 }
2008 if (tb != NULL) {
2009 PyException_SetTraceback(ev, tb);
2010 }
2011 o = future_set_exception((FutureObj*)task, ev);
2012 if (!o) {
2013 /* An exception in Task.set_exception() */
2014 Py_XDECREF(et);
2015 Py_XDECREF(tb);
2016 Py_XDECREF(ev);
2017 goto fail;
2018 }
2019 assert(o == Py_None);
2020 Py_CLEAR(o);
2021
2022 if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2023 /* We've got a BaseException; re-raise it */
2024 PyErr_Restore(et, ev, tb);
2025 goto fail;
2026 }
2027
2028 Py_XDECREF(et);
2029 Py_XDECREF(tb);
2030 Py_XDECREF(ev);
2031
2032 Py_RETURN_NONE;
2033 }
2034
2035 if (result == (PyObject*)task) {
2036 /* We have a task that wants to await on itself */
2037 goto self_await;
2038 }
2039
2040 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2041 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2042 PyObject *wrapper;
2043 PyObject *res;
2044 FutureObj *fut = (FutureObj*)result;
2045
2046 /* Check if `result` future is attached to a different loop */
2047 if (fut->fut_loop != task->task_loop) {
2048 goto different_loop;
2049 }
2050
2051 if (fut->fut_blocking) {
2052 fut->fut_blocking = 0;
2053
2054 /* result.add_done_callback(task._wakeup) */
2055 wrapper = TaskWakeupMethWrapper_new(task);
2056 if (wrapper == NULL) {
2057 goto fail;
2058 }
2059 res = future_add_done_callback((FutureObj*)result, wrapper);
2060 Py_DECREF(wrapper);
2061 if (res == NULL) {
2062 goto fail;
2063 }
2064 Py_DECREF(res);
2065
2066 /* task._fut_waiter = result */
2067 task->task_fut_waiter = result; /* no incref is necessary */
2068
2069 if (task->task_must_cancel) {
2070 PyObject *r;
2071 r = future_cancel(fut);
2072 if (r == NULL) {
2073 return NULL;
2074 }
2075 if (r == Py_True) {
2076 task->task_must_cancel = 0;
2077 }
2078 Py_DECREF(r);
2079 }
2080
2081 Py_RETURN_NONE;
2082 }
2083 else {
2084 goto yield_insteadof_yf;
2085 }
2086 }
2087
2088 /* Check if `result` is a Future-compatible object */
2089 o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2090 if (o == NULL) {
2091 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2092 PyErr_Clear();
2093 }
2094 else {
2095 goto fail;
2096 }
2097 }
2098 else {
2099 if (o == Py_None) {
2100 Py_CLEAR(o);
2101 }
2102 else {
2103 /* `result` is a Future-compatible object */
2104 PyObject *wrapper;
2105 PyObject *res;
2106
2107 int blocking = PyObject_IsTrue(o);
2108 Py_CLEAR(o);
2109 if (blocking < 0) {
2110 goto fail;
2111 }
2112
2113 /* Check if `result` future is attached to a different loop */
2114 PyObject *oloop = PyObject_GetAttrString(result, "_loop");
2115 if (oloop == NULL) {
2116 goto fail;
2117 }
2118 if (oloop != task->task_loop) {
2119 Py_DECREF(oloop);
2120 goto different_loop;
2121 }
2122 else {
2123 Py_DECREF(oloop);
2124 }
2125
2126 if (blocking) {
2127 /* result._asyncio_future_blocking = False */
2128 if (PyObject_SetAttrString(
2129 result, "_asyncio_future_blocking", Py_False) == -1) {
2130 goto fail;
2131 }
2132
2133 /* result.add_done_callback(task._wakeup) */
2134 wrapper = TaskWakeupMethWrapper_new(task);
2135 if (wrapper == NULL) {
2136 goto fail;
2137 }
2138 res = _PyObject_CallMethodIdObjArgs(result,
2139 &PyId_add_done_callback,
2140 wrapper, NULL);
2141 Py_DECREF(wrapper);
2142 if (res == NULL) {
2143 goto fail;
2144 }
2145 Py_DECREF(res);
2146
2147 /* task._fut_waiter = result */
2148 task->task_fut_waiter = result; /* no incref is necessary */
2149
2150 if (task->task_must_cancel) {
2151 PyObject *r;
2152 int is_true;
2153 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2154 if (r == NULL) {
2155 return NULL;
2156 }
2157 is_true = PyObject_IsTrue(r);
2158 Py_DECREF(r);
2159 if (is_true < 0) {
2160 return NULL;
2161 }
2162 else if (is_true) {
2163 task->task_must_cancel = 0;
2164 }
2165 }
2166
2167 Py_RETURN_NONE;
2168 }
2169 else {
2170 goto yield_insteadof_yf;
2171 }
2172 }
2173 }
2174
2175 /* Check if `result` is None */
2176 if (result == Py_None) {
2177 /* Bare yield relinquishes control for one event loop iteration. */
2178 if (task_call_step_soon(task, NULL)) {
2179 goto fail;
2180 }
2181 return result;
2182 }
2183
2184 /* Check if `result` is a generator */
2185 o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
2186 if (o == NULL) {
2187 /* An exception in inspect.isgenerator */
2188 goto fail;
2189 }
2190 res = PyObject_IsTrue(o);
2191 Py_CLEAR(o);
2192 if (res == -1) {
2193 /* An exception while checking if 'val' is True */
2194 goto fail;
2195 }
2196 if (res == 1) {
2197 /* `result` is a generator */
2198 PyObject *ret;
2199 ret = task_set_error_soon(
2200 task, PyExc_RuntimeError,
2201 "yield was used instead of yield from for "
2202 "generator in task %R with %S", task, result);
2203 Py_DECREF(result);
2204 return ret;
2205 }
2206
2207 /* The `result` is none of the above */
2208 Py_DECREF(result);
2209 return task_set_error_soon(
2210 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2211
2212 self_await:
2213 o = task_set_error_soon(
2214 task, PyExc_RuntimeError,
2215 "Task cannot await on itself: %R", task);
2216 Py_DECREF(result);
2217 return o;
2218
2219 yield_insteadof_yf:
2220 o = task_set_error_soon(
2221 task, PyExc_RuntimeError,
2222 "yield was used instead of yield from "
2223 "in task %R with %R",
2224 task, result);
2225 Py_DECREF(result);
2226 return o;
2227
2228 different_loop:
2229 o = task_set_error_soon(
2230 task, PyExc_RuntimeError,
2231 "Task %R got Future %R attached to a different loop",
2232 task, result);
2233 Py_DECREF(result);
2234 return o;
2235
2236 fail:
2237 Py_XDECREF(result);
2238 return NULL;
2239 }
2240
2241 static PyObject *
task_step(TaskObj * task,PyObject * exc)2242 task_step(TaskObj *task, PyObject *exc)
2243 {
2244 PyObject *res;
2245 PyObject *ot;
2246
2247 if (PyDict_SetItem(current_tasks,
2248 task->task_loop, (PyObject*)task) == -1)
2249 {
2250 return NULL;
2251 }
2252
2253 res = task_step_impl(task, exc);
2254
2255 if (res == NULL) {
2256 PyObject *et, *ev, *tb;
2257 PyErr_Fetch(&et, &ev, &tb);
2258 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2259 if (ot == NULL) {
2260 Py_XDECREF(et);
2261 Py_XDECREF(tb);
2262 Py_XDECREF(ev);
2263 return NULL;
2264 }
2265 Py_DECREF(ot);
2266 PyErr_Restore(et, ev, tb);
2267 return NULL;
2268 }
2269 else {
2270 ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2271 if (ot == NULL) {
2272 Py_DECREF(res);
2273 return NULL;
2274 }
2275 else {
2276 Py_DECREF(ot);
2277 return res;
2278 }
2279 }
2280 }
2281
2282 static PyObject *
task_wakeup(TaskObj * task,PyObject * o)2283 task_wakeup(TaskObj *task, PyObject *o)
2284 {
2285 assert(o);
2286
2287 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2288 PyObject *fut_result = NULL;
2289 int res = future_get_result((FutureObj*)o, &fut_result);
2290 PyObject *result;
2291
2292 switch(res) {
2293 case -1:
2294 assert(fut_result == NULL);
2295 return NULL;
2296 case 0:
2297 Py_DECREF(fut_result);
2298 return task_call_step(task, NULL);
2299 default:
2300 assert(res == 1);
2301 result = task_call_step(task, fut_result);
2302 Py_DECREF(fut_result);
2303 return result;
2304 }
2305 }
2306
2307 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2308 if (fut_result == NULL) {
2309 PyObject *et, *ev, *tb;
2310 PyObject *res;
2311
2312 PyErr_Fetch(&et, &ev, &tb);
2313 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2314 PyErr_NormalizeException(&et, &ev, &tb);
2315 }
2316
2317 res = task_call_step(task, ev);
2318
2319 Py_XDECREF(et);
2320 Py_XDECREF(tb);
2321 Py_XDECREF(ev);
2322
2323 return res;
2324 }
2325 else {
2326 Py_DECREF(fut_result);
2327 return task_call_step(task, NULL);
2328 }
2329 }
2330
2331
2332 /*********************** Module **************************/
2333
2334
2335 static void
module_free(void * m)2336 module_free(void *m)
2337 {
2338 Py_CLEAR(current_tasks);
2339 Py_CLEAR(all_tasks);
2340 Py_CLEAR(traceback_extract_stack);
2341 Py_CLEAR(asyncio_get_event_loop);
2342 Py_CLEAR(asyncio_future_repr_info_func);
2343 Py_CLEAR(asyncio_task_repr_info_func);
2344 Py_CLEAR(asyncio_task_get_stack_func);
2345 Py_CLEAR(asyncio_task_print_stack_func);
2346 Py_CLEAR(asyncio_InvalidStateError);
2347 Py_CLEAR(asyncio_CancelledError);
2348 Py_CLEAR(inspect_isgenerator);
2349 }
2350
2351 static int
module_init(void)2352 module_init(void)
2353 {
2354 PyObject *module = NULL;
2355 PyObject *cls;
2356
2357 #define WITH_MOD(NAME) \
2358 Py_CLEAR(module); \
2359 module = PyImport_ImportModule(NAME); \
2360 if (module == NULL) { \
2361 return -1; \
2362 }
2363
2364 #define GET_MOD_ATTR(VAR, NAME) \
2365 VAR = PyObject_GetAttrString(module, NAME); \
2366 if (VAR == NULL) { \
2367 goto fail; \
2368 }
2369
2370 WITH_MOD("asyncio.events")
2371 GET_MOD_ATTR(asyncio_get_event_loop, "get_event_loop")
2372
2373 WITH_MOD("asyncio.base_futures")
2374 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
2375 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
2376 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
2377
2378 WITH_MOD("asyncio.base_tasks")
2379 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
2380 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
2381 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
2382
2383 WITH_MOD("inspect")
2384 GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
2385
2386 WITH_MOD("traceback")
2387 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
2388
2389 WITH_MOD("weakref")
2390 GET_MOD_ATTR(cls, "WeakSet")
2391 all_tasks = PyObject_CallObject(cls, NULL);
2392 Py_CLEAR(cls);
2393 if (all_tasks == NULL) {
2394 goto fail;
2395 }
2396
2397 current_tasks = PyDict_New();
2398 if (current_tasks == NULL) {
2399 goto fail;
2400 }
2401
2402 Py_CLEAR(module);
2403 return 0;
2404
2405 fail:
2406 Py_CLEAR(module);
2407 module_free(NULL);
2408 return -1;
2409
2410 #undef WITH_MOD
2411 #undef GET_MOD_ATTR
2412 }
2413
2414 PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
2415
2416 static struct PyModuleDef _asynciomodule = {
2417 PyModuleDef_HEAD_INIT, /* m_base */
2418 "_asyncio", /* m_name */
2419 module_doc, /* m_doc */
2420 -1, /* m_size */
2421 NULL, /* m_methods */
2422 NULL, /* m_slots */
2423 NULL, /* m_traverse */
2424 NULL, /* m_clear */
2425 (freefunc)module_free /* m_free */
2426 };
2427
2428
2429 PyMODINIT_FUNC
PyInit__asyncio(void)2430 PyInit__asyncio(void)
2431 {
2432 if (module_init() < 0) {
2433 return NULL;
2434 }
2435 if (PyType_Ready(&FutureType) < 0) {
2436 return NULL;
2437 }
2438 if (PyType_Ready(&FutureIterType) < 0) {
2439 return NULL;
2440 }
2441 if (PyType_Ready(&TaskSendMethWrapper_Type) < 0) {
2442 return NULL;
2443 }
2444 if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
2445 return NULL;
2446 }
2447 if (PyType_Ready(&TaskType) < 0) {
2448 return NULL;
2449 }
2450
2451 PyObject *m = PyModule_Create(&_asynciomodule);
2452 if (m == NULL) {
2453 return NULL;
2454 }
2455
2456 Py_INCREF(&FutureType);
2457 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
2458 Py_DECREF(&FutureType);
2459 return NULL;
2460 }
2461
2462 Py_INCREF(&TaskType);
2463 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
2464 Py_DECREF(&TaskType);
2465 return NULL;
2466 }
2467
2468 return m;
2469 }
2470