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