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