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