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 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 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 * 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 * 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 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 * 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 * 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 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 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 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 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 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 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 * 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 * 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 * 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 * 1079 FutureIter_close(futureiterobject *self, PyObject *arg) 1080 { 1081 Py_CLEAR(self->future); 1082 Py_RETURN_NONE; 1083 } 1084 1085 static int 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 * 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 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 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 * 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 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 * 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 * 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 * 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 1245 TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o) 1246 { 1247 Py_CLEAR(o->ww_task); 1248 return 0; 1249 } 1250 1251 static int 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 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 * 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 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 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 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 * 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 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 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 * 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 * 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 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 * 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 * 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 * 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 * 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 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 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 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