blob: b615c48c431828696af8cf7628429265c844dfba [file] [log] [blame]
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001#include "Python.h"
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002#include "pycore_pyerrors.h" // _PyErr_ClearExcState()
Victor Stinner4a21e572020-04-15 02:35:41 +02003#include <stddef.h> // offsetof()
INADA Naoki9e4e38e2016-10-09 14:44:47 +09004
5
Yury Selivanova0c1ba62016-10-28 12:52:37 -04006/*[clinic input]
7module _asyncio
8[clinic start generated code]*/
9/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
10
11
INADA Naoki9e4e38e2016-10-09 14:44:47 +090012/* identifiers used from some functions */
Yury Selivanova70232f2017-12-13 14:49:42 -050013_Py_IDENTIFIER(__asyncio_running_event_loop__);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +030014_Py_IDENTIFIER(_asyncio_future_blocking);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040015_Py_IDENTIFIER(add_done_callback);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090016_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040017_Py_IDENTIFIER(cancel);
Yury Selivanova70232f2017-12-13 14:49:42 -050018_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040019_Py_IDENTIFIER(send);
20_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090021
22
INADA Naoki9f2ce252016-10-15 15:39:19 +090023/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020024static PyObject *asyncio_mod;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020025static PyObject *traceback_extract_stack;
26static PyObject *asyncio_get_event_loop_policy;
27static PyObject *asyncio_future_repr_info_func;
28static PyObject *asyncio_iscoroutine_func;
29static PyObject *asyncio_task_get_stack_func;
30static PyObject *asyncio_task_print_stack_func;
31static PyObject *asyncio_task_repr_info_func;
32static PyObject *asyncio_InvalidStateError;
33static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050034static PyObject *context_kwname;
Ben Harper321def82019-10-07 12:19:58 -040035static int module_initialized;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020036
Yury Selivanov9d411c12018-01-23 15:10:03 -050037static PyObject *cached_running_holder;
38static volatile uint64_t cached_running_holder_tsid;
39
Alex Grönholmcca4eec2018-08-09 00:06:47 +030040/* Counter for autogenerated Task names */
41static uint64_t task_name_counter = 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020042
Yury Selivanovca9b36c2017-12-23 15:04:15 -050043/* WeakSet containing all alive tasks. */
44static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020045
46/* Dictionary containing tasks that are currently active in
47 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050048static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090049
Yury Selivanova9d7e552017-12-19 07:18:45 -050050/* An isinstance type cache for the 'is_coroutine()' function. */
51static PyObject *iscoroutine_typecache;
52
INADA Naoki9e4e38e2016-10-09 14:44:47 +090053
INADA Naoki9e4e38e2016-10-09 14:44:47 +090054typedef enum {
55 STATE_PENDING,
56 STATE_CANCELLED,
57 STATE_FINISHED
58} fut_state;
59
Yury Selivanova0c1ba62016-10-28 12:52:37 -040060#define FutureObj_HEAD(prefix) \
61 PyObject_HEAD \
62 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050063 PyObject *prefix##_callback0; \
Yury Selivanov994269c2018-09-27 14:55:55 -040064 PyObject *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040065 PyObject *prefix##_callbacks; \
66 PyObject *prefix##_exception; \
67 PyObject *prefix##_result; \
68 PyObject *prefix##_source_tb; \
Chris Jerdonek1ce58412020-05-15 16:55:50 -070069 PyObject *prefix##_cancel_msg; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040070 fut_state prefix##_state; \
71 int prefix##_log_tb; \
72 int prefix##_blocking; \
73 PyObject *dict; \
Chris Jerdonekda742ba2020-05-17 22:47:31 -070074 PyObject *prefix##_weakreflist; \
75 _PyErr_StackItem prefix##_cancelled_exc_state;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040076
77typedef struct {
78 FutureObj_HEAD(fut)
79} FutureObj;
80
81typedef struct {
82 FutureObj_HEAD(task)
83 PyObject *task_fut_waiter;
84 PyObject *task_coro;
Alex Grönholmcca4eec2018-08-09 00:06:47 +030085 PyObject *task_name;
Yury Selivanov994269c2018-09-27 14:55:55 -040086 PyObject *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040087 int task_must_cancel;
88 int task_log_destroy_pending;
89} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090090
91typedef struct {
92 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040093 TaskObj *sw_task;
94 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030095} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090096
Yury Selivanova0c1ba62016-10-28 12:52:37 -040097typedef struct {
98 PyObject_HEAD
99 TaskObj *ww_task;
100} TaskWakeupMethWrapper;
101
Yury Selivanov9d411c12018-01-23 15:10:03 -0500102typedef struct {
103 PyObject_HEAD
104 PyObject *rl_loop;
105#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
106 pid_t rl_pid;
107#endif
108} PyRunningLoopHolder;
109
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400110
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500111static PyTypeObject FutureType;
112static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500113static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500114
115
Dong-hee Na1b55b652020-02-17 19:09:15 +0900116#define Future_CheckExact(obj) Py_IS_TYPE(obj, &FutureType)
117#define Task_CheckExact(obj) Py_IS_TYPE(obj, &TaskType)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500118
119#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
120#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
121
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400122#include "clinic/_asynciomodule.c.h"
123
124
125/*[clinic input]
126class _asyncio.Future "FutureObj *" "&Future_Type"
127[clinic start generated code]*/
128/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
129
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500130
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400131/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500132static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900133
Yury Selivanov9d411c12018-01-23 15:10:03 -0500134static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
135
Yury Selivanova70232f2017-12-13 14:49:42 -0500136
137static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500138_is_coroutine(PyObject *coro)
139{
140 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
141 to check if it's another coroutine flavour.
142
143 Do this check after 'future_init()'; in case we need to raise
144 an error, __del__ needs a properly initialized object.
145 */
Petr Viktorinffd97532020-02-11 17:46:57 +0100146 PyObject *res = PyObject_CallOneArg(asyncio_iscoroutine_func, coro);
Yury Selivanova9d7e552017-12-19 07:18:45 -0500147 if (res == NULL) {
148 return -1;
149 }
150
151 int is_res_true = PyObject_IsTrue(res);
152 Py_DECREF(res);
153 if (is_res_true <= 0) {
154 return is_res_true;
155 }
156
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200157 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500158 /* Just in case we don't want to cache more than 100
159 positive types. That shouldn't ever happen, unless
160 someone stressing the system on purpose.
161 */
162 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
163 return -1;
164 }
165 }
166
167 return 1;
168}
169
170
171static inline int
172is_coroutine(PyObject *coro)
173{
174 if (PyCoro_CheckExact(coro)) {
175 return 1;
176 }
177
178 /* Check if `type(coro)` is in the cache.
179 Caching makes is_coroutine() function almost as fast as
180 PyCoro_CheckExact() for non-native coroutine-like objects
181 (like coroutines compiled with Cython).
182
183 asyncio.iscoroutine() has its own type caching mechanism.
184 This cache allows us to avoid the cost of even calling
185 a pure-Python function in 99.9% cases.
186 */
187 int has_it = PySet_Contains(
188 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
189 if (has_it == 0) {
190 /* type(coro) is not in iscoroutine_typecache */
191 return _is_coroutine(coro);
192 }
193
Leo Ariasc3d95082018-02-03 18:36:10 -0600194 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500195 type(coro) is in iscoroutine_typecache
196 */
197 return has_it;
198}
199
200
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500201static PyObject *
202get_future_loop(PyObject *fut)
203{
204 /* Implementation of `asyncio.futures._get_loop` */
205
206 _Py_IDENTIFIER(get_loop);
207 _Py_IDENTIFIER(_loop);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300208 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500209
210 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
211 PyObject *loop = ((FutureObj *)fut)->fut_loop;
212 Py_INCREF(loop);
213 return loop;
214 }
215
Serhiy Storchaka66553542018-05-20 16:30:31 +0300216 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
217 return NULL;
218 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500219 if (getloop != NULL) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200220 PyObject *res = PyObject_CallNoArgs(getloop);
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500221 Py_DECREF(getloop);
222 return res;
223 }
224
225 return _PyObject_GetAttrId(fut, &PyId__loop);
226}
227
228
Yury Selivanova9d7e552017-12-19 07:18:45 -0500229static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500230get_running_loop(PyObject **loop)
231{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500232 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500233
Yury Selivanov9d411c12018-01-23 15:10:03 -0500234 PyThreadState *ts = PyThreadState_Get();
Victor Stinner5c3cda02020-03-25 21:23:53 +0100235 uint64_t ts_id = PyThreadState_GetID(ts);
236 if (ts_id == cached_running_holder_tsid && cached_running_holder != NULL) {
Yury Selivanov9d411c12018-01-23 15:10:03 -0500237 // Fast path, check the cache.
238 rl = cached_running_holder; // borrowed
239 }
240 else {
Victor Stinner0e427c62020-03-25 21:22:55 +0100241 PyObject *ts_dict = _PyThreadState_GetDict(ts); // borrowed
242 if (ts_dict == NULL) {
Yury Selivanov9d411c12018-01-23 15:10:03 -0500243 goto not_found;
244 }
245
246 rl = _PyDict_GetItemIdWithError(
Victor Stinner0e427c62020-03-25 21:22:55 +0100247 ts_dict, &PyId___asyncio_running_event_loop__); // borrowed
Yury Selivanov9d411c12018-01-23 15:10:03 -0500248 if (rl == NULL) {
249 if (PyErr_Occurred()) {
250 goto error;
251 }
252 else {
253 goto not_found;
254 }
255 }
256
257 cached_running_holder = rl; // borrowed
Victor Stinner5c3cda02020-03-25 21:23:53 +0100258 cached_running_holder_tsid = ts_id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500259 }
260
Dong-hee Na1b55b652020-02-17 19:09:15 +0900261 assert(Py_IS_TYPE(rl, &PyRunningLoopHolder_Type));
Yury Selivanov9d411c12018-01-23 15:10:03 -0500262 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500263
264 if (running_loop == Py_None) {
265 goto not_found;
266 }
267
Yury Selivanov9d411c12018-01-23 15:10:03 -0500268#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
269 /* On Windows there is no getpid, but there is also no os.fork(),
270 so there is no need for this check.
271 */
272 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
273 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500274 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500275#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500276
Yury Selivanov9d411c12018-01-23 15:10:03 -0500277 Py_INCREF(running_loop);
278 *loop = running_loop;
279 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500280
281not_found:
282 *loop = NULL;
283 return 0;
284
Yury Selivanova70232f2017-12-13 14:49:42 -0500285error:
286 *loop = NULL;
287 return -1;
288}
289
290
291static int
292set_running_loop(PyObject *loop)
293{
Miss Islington (bot)fbd71f62020-07-08 12:47:20 -0700294 PyObject *ts_dict = NULL;
Yury Selivanova70232f2017-12-13 14:49:42 -0500295
Miss Islington (bot)fbd71f62020-07-08 12:47:20 -0700296 PyThreadState *tstate = PyThreadState_Get();
297 if (tstate != NULL) {
298 ts_dict = _PyThreadState_GetDict(tstate); // borrowed
299 }
300
Yury Selivanova70232f2017-12-13 14:49:42 -0500301 if (ts_dict == NULL) {
302 PyErr_SetString(
303 PyExc_RuntimeError, "thread-local storage is not available");
304 return -1;
305 }
306
Yury Selivanov9d411c12018-01-23 15:10:03 -0500307 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
308 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500309 return -1;
310 }
311
Yury Selivanova70232f2017-12-13 14:49:42 -0500312 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500313 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
314 {
315 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500316 return -1;
317 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500318 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500319
Miss Islington (bot)fbd71f62020-07-08 12:47:20 -0700320 cached_running_holder = (PyObject *)rl;
321 cached_running_holder_tsid = PyThreadState_GetID(tstate);
322
Yury Selivanova70232f2017-12-13 14:49:42 -0500323 return 0;
324}
325
326
327static PyObject *
328get_event_loop(void)
329{
330 PyObject *loop;
331 PyObject *policy;
332
333 if (get_running_loop(&loop)) {
334 return NULL;
335 }
336 if (loop != NULL) {
337 return loop;
338 }
339
Victor Stinner2ff58a22019-06-17 14:27:23 +0200340 policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy);
Yury Selivanova70232f2017-12-13 14:49:42 -0500341 if (policy == NULL) {
342 return NULL;
343 }
344
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200345 loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
Yury Selivanova70232f2017-12-13 14:49:42 -0500346 Py_DECREF(policy);
347 return loop;
348}
349
350
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900351static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400352call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500353{
354 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500355 PyObject *stack[3];
356 Py_ssize_t nargs;
357
358 if (ctx == NULL) {
359 handle = _PyObject_CallMethodIdObjArgs(
360 loop, &PyId_call_soon, func, arg, NULL);
361 }
362 else {
363 /* Use FASTCALL to pass a keyword-only argument to call_soon */
364
365 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
366 if (callable == NULL) {
367 return -1;
368 }
369
370 /* All refs in 'stack' are borrowed. */
371 nargs = 1;
372 stack[0] = func;
373 if (arg != NULL) {
374 stack[1] = arg;
375 nargs++;
376 }
377 stack[nargs] = (PyObject *)ctx;
378
Petr Viktorinffd97532020-02-11 17:46:57 +0100379 handle = PyObject_Vectorcall(callable, stack, nargs, context_kwname);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500380 Py_DECREF(callable);
381 }
382
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500383 if (handle == NULL) {
384 return -1;
385 }
386 Py_DECREF(handle);
387 return 0;
388}
389
390
391static inline int
392future_is_alive(FutureObj *fut)
393{
394 return fut->fut_loop != NULL;
395}
396
397
398static inline int
399future_ensure_alive(FutureObj *fut)
400{
401 if (!future_is_alive(fut)) {
402 PyErr_SetString(PyExc_RuntimeError,
403 "Future object is not initialized.");
404 return -1;
405 }
406 return 0;
407}
408
409
410#define ENSURE_FUTURE_ALIVE(fut) \
411 do { \
412 assert(Future_Check(fut) || Task_Check(fut)); \
413 if (future_ensure_alive((FutureObj*)fut)) { \
414 return NULL; \
415 } \
416 } while(0);
417
418
419static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400420future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900421{
422 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500423 Py_ssize_t i;
424
425 if (fut->fut_callback0 != NULL) {
426 /* There's a 1st callback */
427
428 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500429 fut->fut_loop, fut->fut_callback0,
430 (PyObject *)fut, fut->fut_context0);
431
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500432 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500433 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500434 if (ret) {
435 /* If an error occurs in pure-Python implementation,
436 all callbacks are cleared. */
437 Py_CLEAR(fut->fut_callbacks);
438 return ret;
439 }
440
441 /* we called the first callback, now try calling
442 callbacks from the 'fut_callbacks' list. */
443 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900444
445 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500446 /* No more callbacks, return. */
447 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900448 }
449
450 len = PyList_GET_SIZE(fut->fut_callbacks);
451 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500452 /* The list of callbacks was empty; clear it and return. */
453 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900454 return 0;
455 }
456
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900457 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500458 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
459 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
460 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900461
Yury Selivanov994269c2018-09-27 14:55:55 -0400462 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500463 /* If an error occurs in pure-Python implementation,
464 all callbacks are cleared. */
465 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900466 return -1;
467 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900468 }
469
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500470 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900471 return 0;
472}
473
Oren Milmand019bc82018-02-13 12:28:33 +0200474
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900475static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400476future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900477{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300478 PyObject *res;
479 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900480 _Py_IDENTIFIER(get_debug);
481
Oren Milmand019bc82018-02-13 12:28:33 +0200482 // Same to FutureObj_clear() but not clearing fut->dict
483 Py_CLEAR(fut->fut_loop);
484 Py_CLEAR(fut->fut_callback0);
485 Py_CLEAR(fut->fut_context0);
486 Py_CLEAR(fut->fut_callbacks);
487 Py_CLEAR(fut->fut_result);
488 Py_CLEAR(fut->fut_exception);
489 Py_CLEAR(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700490 Py_CLEAR(fut->fut_cancel_msg);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700491 _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
Oren Milmand019bc82018-02-13 12:28:33 +0200492
493 fut->fut_state = STATE_PENDING;
494 fut->fut_log_tb = 0;
495 fut->fut_blocking = 0;
496
Serhiy Storchakabca49392017-09-03 08:10:14 +0300497 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500498 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900499 if (loop == NULL) {
500 return -1;
501 }
502 }
503 else {
504 Py_INCREF(loop);
505 }
Oren Milmand019bc82018-02-13 12:28:33 +0200506 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900507
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200508 res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900509 if (res == NULL) {
510 return -1;
511 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300512 is_true = PyObject_IsTrue(res);
513 Py_DECREF(res);
514 if (is_true < 0) {
515 return -1;
516 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400517 if (is_true && !_Py_IsFinalizing()) {
518 /* Only try to capture the traceback if the interpreter is not being
519 finalized. The original motivation to add a `_Py_IsFinalizing()`
520 call was to prevent SIGSEGV when a Future is created in a __del__
521 method, which is called during the interpreter shutdown and the
522 traceback module is already unloaded.
523 */
Victor Stinner2ff58a22019-06-17 14:27:23 +0200524 fut->fut_source_tb = PyObject_CallNoArgs(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900525 if (fut->fut_source_tb == NULL) {
526 return -1;
527 }
528 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900529
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900530 return 0;
531}
532
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900533static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400534future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900535{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500536 if (future_ensure_alive(fut)) {
537 return NULL;
538 }
539
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900540 if (fut->fut_state != STATE_PENDING) {
541 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
542 return NULL;
543 }
544
Serhiy Storchakabca49392017-09-03 08:10:14 +0300545 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900546 Py_INCREF(res);
547 fut->fut_result = res;
548 fut->fut_state = STATE_FINISHED;
549
Yury Selivanov22feeb82018-01-24 11:31:01 -0500550 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900551 return NULL;
552 }
553 Py_RETURN_NONE;
554}
555
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900556static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400557future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900558{
559 PyObject *exc_val = NULL;
560
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900561 if (fut->fut_state != STATE_PENDING) {
562 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
563 return NULL;
564 }
565
566 if (PyExceptionClass_Check(exc)) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200567 exc_val = PyObject_CallNoArgs(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900568 if (exc_val == NULL) {
569 return NULL;
570 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300571 if (fut->fut_state != STATE_PENDING) {
572 Py_DECREF(exc_val);
573 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
574 return NULL;
575 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900576 }
577 else {
578 exc_val = exc;
579 Py_INCREF(exc_val);
580 }
581 if (!PyExceptionInstance_Check(exc_val)) {
582 Py_DECREF(exc_val);
583 PyErr_SetString(PyExc_TypeError, "invalid exception object");
584 return NULL;
585 }
Andy Lesterdffe4c02020-03-04 07:15:20 -0600586 if (Py_IS_TYPE(exc_val, (PyTypeObject *)PyExc_StopIteration)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900587 Py_DECREF(exc_val);
588 PyErr_SetString(PyExc_TypeError,
589 "StopIteration interacts badly with generators "
590 "and cannot be raised into a Future");
591 return NULL;
592 }
593
Serhiy Storchakabca49392017-09-03 08:10:14 +0300594 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900595 fut->fut_exception = exc_val;
596 fut->fut_state = STATE_FINISHED;
597
Yury Selivanov22feeb82018-01-24 11:31:01 -0500598 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900599 return NULL;
600 }
601
602 fut->fut_log_tb = 1;
603 Py_RETURN_NONE;
604}
605
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700606static PyObject *
607create_cancelled_error(PyObject *msg)
608{
609 PyObject *exc;
610 if (msg == NULL || msg == Py_None) {
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700611 exc = PyObject_CallNoArgs(asyncio_CancelledError);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700612 } else {
613 exc = PyObject_CallOneArg(asyncio_CancelledError, msg);
614 }
615 return exc;
616}
617
618static void
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700619future_set_cancelled_error(FutureObj *fut)
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700620{
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700621 PyObject *exc = create_cancelled_error(fut->fut_cancel_msg);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700622 PyErr_SetObject(asyncio_CancelledError, exc);
623 Py_DECREF(exc);
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700624
625 _PyErr_ChainStackItem(&fut->fut_cancelled_exc_state);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700626}
627
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400628static int
629future_get_result(FutureObj *fut, PyObject **result)
630{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400631 if (fut->fut_state == STATE_CANCELLED) {
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700632 future_set_cancelled_error(fut);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300633 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400634 }
635
636 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300637 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
638 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400639 }
640
641 fut->fut_log_tb = 0;
642 if (fut->fut_exception != NULL) {
643 Py_INCREF(fut->fut_exception);
644 *result = fut->fut_exception;
645 return 1;
646 }
647
648 Py_INCREF(fut->fut_result);
649 *result = fut->fut_result;
650 return 0;
651}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900652
653static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400654future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900655{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500656 if (!future_is_alive(fut)) {
657 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
658 return NULL;
659 }
660
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900661 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500662 /* The future is done/cancelled, so schedule the callback
663 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500664 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900665 return NULL;
666 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900667 }
668 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500669 /* The future is pending, add a callback.
670
671 Callbacks in the future object are stored as follows:
672
673 callback0 -- a pointer to the first callback
674 callbacks -- a list of 2nd, 3rd, ... callbacks
675
676 Invariants:
677
678 * callbacks != NULL:
679 There are some callbacks in in the list. Just
680 add the new callback to it.
681
682 * callbacks == NULL and callback0 == NULL:
683 This is the first callback. Set it to callback0.
684
685 * callbacks == NULL and callback0 != NULL:
686 This is a second callback. Initialize callbacks
687 with a new list and add the new callback to it.
688 */
689
Yury Selivanovf23746a2018-01-22 19:11:18 -0500690 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500691 Py_INCREF(arg);
692 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500693 Py_INCREF(ctx);
694 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500695 }
696 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500697 PyObject *tup = PyTuple_New(2);
698 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500699 return NULL;
700 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500701 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500702 PyTuple_SET_ITEM(tup, 0, arg);
703 Py_INCREF(ctx);
704 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
705
706 if (fut->fut_callbacks != NULL) {
707 int err = PyList_Append(fut->fut_callbacks, tup);
708 if (err) {
709 Py_DECREF(tup);
710 return NULL;
711 }
712 Py_DECREF(tup);
713 }
714 else {
715 fut->fut_callbacks = PyList_New(1);
716 if (fut->fut_callbacks == NULL) {
717 return NULL;
718 }
719
720 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
721 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900722 }
723 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500724
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900725 Py_RETURN_NONE;
726}
727
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400728static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700729future_cancel(FutureObj *fut, PyObject *msg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400730{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000731 fut->fut_log_tb = 0;
732
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400733 if (fut->fut_state != STATE_PENDING) {
734 Py_RETURN_FALSE;
735 }
736 fut->fut_state = STATE_CANCELLED;
737
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700738 Py_XINCREF(msg);
739 Py_XSETREF(fut->fut_cancel_msg, msg);
740
Yury Selivanov22feeb82018-01-24 11:31:01 -0500741 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400742 return NULL;
743 }
744
745 Py_RETURN_TRUE;
746}
747
748/*[clinic input]
749_asyncio.Future.__init__
750
751 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300752 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400753
754This class is *almost* compatible with concurrent.futures.Future.
755
756 Differences:
757
758 - result() and exception() do not take a timeout argument and
759 raise an exception when the future isn't done yet.
760
761 - Callbacks registered with add_done_callback() are always called
762 via the event loop's call_soon_threadsafe().
763
764 - This class is not compatible with the wait() and as_completed()
765 methods in the concurrent.futures package.
766[clinic start generated code]*/
767
768static int
769_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300770/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400771
772{
773 return future_init(self, loop);
774}
775
776static int
777FutureObj_clear(FutureObj *fut)
778{
779 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500780 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500781 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400782 Py_CLEAR(fut->fut_callbacks);
783 Py_CLEAR(fut->fut_result);
784 Py_CLEAR(fut->fut_exception);
785 Py_CLEAR(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700786 Py_CLEAR(fut->fut_cancel_msg);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700787 _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400788 Py_CLEAR(fut->dict);
789 return 0;
790}
791
792static int
793FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
794{
795 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500796 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500797 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400798 Py_VISIT(fut->fut_callbacks);
799 Py_VISIT(fut->fut_result);
800 Py_VISIT(fut->fut_exception);
801 Py_VISIT(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700802 Py_VISIT(fut->fut_cancel_msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400803 Py_VISIT(fut->dict);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700804
805 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
806 Py_VISIT(exc_state->exc_type);
807 Py_VISIT(exc_state->exc_value);
808 Py_VISIT(exc_state->exc_traceback);
809
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400810 return 0;
811}
812
813/*[clinic input]
814_asyncio.Future.result
815
816Return the result this future represents.
817
818If the future has been cancelled, raises CancelledError. If the
819future's result isn't yet available, raises InvalidStateError. If
820the future is done and has an exception set, this exception is raised.
821[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900822
823static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400824_asyncio_Future_result_impl(FutureObj *self)
825/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
826{
827 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500828
829 if (!future_is_alive(self)) {
830 PyErr_SetString(asyncio_InvalidStateError,
831 "Future object is not initialized.");
832 return NULL;
833 }
834
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400835 int res = future_get_result(self, &result);
836
837 if (res == -1) {
838 return NULL;
839 }
840
841 if (res == 0) {
842 return result;
843 }
844
845 assert(res == 1);
846
847 PyErr_SetObject(PyExceptionInstance_Class(result), result);
848 Py_DECREF(result);
849 return NULL;
850}
851
852/*[clinic input]
853_asyncio.Future.exception
854
855Return the exception that was set on this future.
856
857The exception (or None if no exception was set) is returned only if
858the future is done. If the future has been cancelled, raises
859CancelledError. If the future isn't done yet, raises
860InvalidStateError.
861[clinic start generated code]*/
862
863static PyObject *
864_asyncio_Future_exception_impl(FutureObj *self)
865/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
866{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500867 if (!future_is_alive(self)) {
868 PyErr_SetString(asyncio_InvalidStateError,
869 "Future object is not initialized.");
870 return NULL;
871 }
872
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400873 if (self->fut_state == STATE_CANCELLED) {
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700874 future_set_cancelled_error(self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400875 return NULL;
876 }
877
878 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300879 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400880 return NULL;
881 }
882
883 if (self->fut_exception != NULL) {
884 self->fut_log_tb = 0;
885 Py_INCREF(self->fut_exception);
886 return self->fut_exception;
887 }
888
889 Py_RETURN_NONE;
890}
891
892/*[clinic input]
893_asyncio.Future.set_result
894
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500895 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400896 /
897
898Mark the future done and set its result.
899
900If the future is already done when this method is called, raises
901InvalidStateError.
902[clinic start generated code]*/
903
904static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500905_asyncio_Future_set_result(FutureObj *self, PyObject *result)
906/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400907{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500908 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500909 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400910}
911
912/*[clinic input]
913_asyncio.Future.set_exception
914
Serhiy Storchakabca49392017-09-03 08:10:14 +0300915 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400916 /
917
918Mark the future done and set an exception.
919
920If the future is already done when this method is called, raises
921InvalidStateError.
922[clinic start generated code]*/
923
924static PyObject *
925_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300926/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400927{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500928 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400929 return future_set_exception(self, exception);
930}
931
932/*[clinic input]
933_asyncio.Future.add_done_callback
934
Serhiy Storchakabca49392017-09-03 08:10:14 +0300935 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400936 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500937 *
938 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400939
940Add a callback to be run when the future becomes done.
941
942The callback is called with a single argument - the future object. If
943the future is already done when this is called, the callback is
944scheduled with call_soon.
945[clinic start generated code]*/
946
947static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500948_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
949 PyObject *context)
950/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400951{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500952 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400953 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500954 if (context == NULL) {
955 return NULL;
956 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400957 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500958 Py_DECREF(context);
959 return res;
960 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400961 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400962}
963
964/*[clinic input]
965_asyncio.Future.remove_done_callback
966
Serhiy Storchakabca49392017-09-03 08:10:14 +0300967 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400968 /
969
970Remove all instances of a callback from the "call when done" list.
971
972Returns the number of callbacks removed.
973[clinic start generated code]*/
974
975static PyObject *
976_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300977/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900978{
979 PyObject *newlist;
980 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500981 Py_ssize_t cleared_callback0 = 0;
982
983 ENSURE_FUTURE_ALIVE(self)
984
985 if (self->fut_callback0 != NULL) {
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300986 int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500987 if (cmp == -1) {
988 return NULL;
989 }
990 if (cmp == 1) {
991 /* callback0 == fn */
992 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500993 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500994 cleared_callback0 = 1;
995 }
996 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900997
Serhiy Storchakabca49392017-09-03 08:10:14 +0300998 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500999 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001000 }
1001
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001002 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001003 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001004 Py_CLEAR(self->fut_callbacks);
1005 return PyLong_FromSsize_t(cleared_callback0);
1006 }
1007
1008 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -05001009 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001010 int cmp = PyObject_RichCompareBool(
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001011 PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001012 if (cmp == -1) {
1013 return NULL;
1014 }
1015 if (cmp == 1) {
1016 /* callbacks[0] == fn */
1017 Py_CLEAR(self->fut_callbacks);
1018 return PyLong_FromSsize_t(1 + cleared_callback0);
1019 }
1020 /* callbacks[0] != fn and len(callbacks) == 1 */
1021 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001022 }
1023
1024 newlist = PyList_New(len);
1025 if (newlist == NULL) {
1026 return NULL;
1027 }
1028
Yury Selivanov84af9032017-03-02 23:46:56 -05001029 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001030 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001031 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001032 Py_INCREF(item);
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001033 ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001034 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001035 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001036 PyList_SET_ITEM(newlist, j, item);
1037 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001038 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -04001039 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001040 ret = PyList_Append(newlist, item);
1041 }
1042 Py_DECREF(item);
1043 if (ret < 0) {
1044 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001045 }
1046 }
1047
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001048 if (j == 0) {
1049 Py_CLEAR(self->fut_callbacks);
1050 Py_DECREF(newlist);
1051 return PyLong_FromSsize_t(len + cleared_callback0);
1052 }
1053
Serhiy Storchakabca49392017-09-03 08:10:14 +03001054 if (j < len) {
Victor Stinner60ac6ed2020-02-07 23:18:08 +01001055 Py_SET_SIZE(newlist, j);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001056 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001057 j = PyList_GET_SIZE(newlist);
1058 len = PyList_GET_SIZE(self->fut_callbacks);
1059 if (j != len) {
1060 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1061 goto fail;
1062 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001063 }
1064 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001065 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001066
1067fail:
1068 Py_DECREF(newlist);
1069 return NULL;
1070}
1071
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001072/*[clinic input]
1073_asyncio.Future.cancel
1074
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001075 msg: object = None
1076
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001077Cancel the future and schedule callbacks.
1078
1079If the future is already done or cancelled, return False. Otherwise,
1080change the future's state to cancelled, schedule the callbacks and
1081return True.
1082[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001083
1084static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001085_asyncio_Future_cancel_impl(FutureObj *self, PyObject *msg)
1086/*[clinic end generated code: output=3edebbc668e5aba3 input=925eb545251f2c5a]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001087{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001088 ENSURE_FUTURE_ALIVE(self)
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001089 return future_cancel(self, msg);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001090}
1091
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001092/*[clinic input]
1093_asyncio.Future.cancelled
1094
1095Return True if the future was cancelled.
1096[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001097
1098static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001099_asyncio_Future_cancelled_impl(FutureObj *self)
1100/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001101{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001102 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001103 Py_RETURN_TRUE;
1104 }
1105 else {
1106 Py_RETURN_FALSE;
1107 }
1108}
1109
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001110/*[clinic input]
1111_asyncio.Future.done
1112
1113Return True if the future is done.
1114
1115Done means either that a result / exception are available, or that the
1116future was cancelled.
1117[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001118
1119static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001120_asyncio_Future_done_impl(FutureObj *self)
1121/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001122{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001123 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001124 Py_RETURN_FALSE;
1125 }
1126 else {
1127 Py_RETURN_TRUE;
1128 }
1129}
1130
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001131/*[clinic input]
1132_asyncio.Future.get_loop
1133
1134Return the event loop the Future is bound to.
1135[clinic start generated code]*/
1136
1137static PyObject *
1138_asyncio_Future_get_loop_impl(FutureObj *self)
1139/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1140{
Andrew Svetlovdad6be52019-11-13 23:36:46 +02001141 ENSURE_FUTURE_ALIVE(self)
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001142 Py_INCREF(self->fut_loop);
1143 return self->fut_loop;
1144}
1145
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001146static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001147FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001148{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001149 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001150 Py_RETURN_TRUE;
1151 }
1152 else {
1153 Py_RETURN_FALSE;
1154 }
1155}
1156
1157static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001158FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001159{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001160 if (future_ensure_alive(fut)) {
1161 return -1;
1162 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001163 if (val == NULL) {
1164 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1165 return -1;
1166 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001167
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001168 int is_true = PyObject_IsTrue(val);
1169 if (is_true < 0) {
1170 return -1;
1171 }
1172 fut->fut_blocking = is_true;
1173 return 0;
1174}
1175
1176static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001177FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001178{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001179 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001180 if (fut->fut_log_tb) {
1181 Py_RETURN_TRUE;
1182 }
1183 else {
1184 Py_RETURN_FALSE;
1185 }
1186}
1187
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001188static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001189FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001190{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001191 if (val == NULL) {
1192 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1193 return -1;
1194 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001195 int is_true = PyObject_IsTrue(val);
1196 if (is_true < 0) {
1197 return -1;
1198 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001199 if (is_true) {
1200 PyErr_SetString(PyExc_ValueError,
1201 "_log_traceback can only be set to False");
1202 return -1;
1203 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001204 fut->fut_log_tb = is_true;
1205 return 0;
1206}
1207
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001208static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001209FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001210{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001211 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001212 Py_RETURN_NONE;
1213 }
1214 Py_INCREF(fut->fut_loop);
1215 return fut->fut_loop;
1216}
1217
1218static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001219FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001220{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001221 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001222
1223 ENSURE_FUTURE_ALIVE(fut)
1224
Yury Selivanovf23746a2018-01-22 19:11:18 -05001225 if (fut->fut_callback0 == NULL) {
1226 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001227 Py_RETURN_NONE;
1228 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001229
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001230 Py_INCREF(fut->fut_callbacks);
1231 return fut->fut_callbacks;
1232 }
1233
Yury Selivanovf23746a2018-01-22 19:11:18 -05001234 Py_ssize_t len = 1;
1235 if (fut->fut_callbacks != NULL) {
1236 len += PyList_GET_SIZE(fut->fut_callbacks);
1237 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001238
Yury Selivanovf23746a2018-01-22 19:11:18 -05001239
1240 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001241 if (new_list == NULL) {
1242 return NULL;
1243 }
1244
Yury Selivanovf23746a2018-01-22 19:11:18 -05001245 PyObject *tup0 = PyTuple_New(2);
1246 if (tup0 == NULL) {
1247 Py_DECREF(new_list);
1248 return NULL;
1249 }
1250
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001251 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001252 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1253 assert(fut->fut_context0 != NULL);
1254 Py_INCREF(fut->fut_context0);
1255 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1256
1257 PyList_SET_ITEM(new_list, 0, tup0);
1258
1259 if (fut->fut_callbacks != NULL) {
1260 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1261 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1262 Py_INCREF(cb);
1263 PyList_SET_ITEM(new_list, i + 1, cb);
1264 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001265 }
1266
1267 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001268}
1269
1270static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001271FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001272{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001273 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001274 if (fut->fut_result == NULL) {
1275 Py_RETURN_NONE;
1276 }
1277 Py_INCREF(fut->fut_result);
1278 return fut->fut_result;
1279}
1280
1281static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001282FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001283{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001284 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001285 if (fut->fut_exception == NULL) {
1286 Py_RETURN_NONE;
1287 }
1288 Py_INCREF(fut->fut_exception);
1289 return fut->fut_exception;
1290}
1291
1292static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001293FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001294{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001295 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001296 Py_RETURN_NONE;
1297 }
1298 Py_INCREF(fut->fut_source_tb);
1299 return fut->fut_source_tb;
1300}
1301
1302static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001303FutureObj_get_cancel_message(FutureObj *fut, void *Py_UNUSED(ignored))
1304{
1305 if (fut->fut_cancel_msg == NULL) {
1306 Py_RETURN_NONE;
1307 }
1308 Py_INCREF(fut->fut_cancel_msg);
1309 return fut->fut_cancel_msg;
1310}
1311
1312static int
1313FutureObj_set_cancel_message(FutureObj *fut, PyObject *msg,
1314 void *Py_UNUSED(ignored))
1315{
1316 if (msg == NULL) {
1317 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1318 return -1;
1319 }
1320 Py_INCREF(msg);
1321 Py_XSETREF(fut->fut_cancel_msg, msg);
1322 return 0;
1323}
1324
1325static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001326FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001327{
1328 _Py_IDENTIFIER(PENDING);
1329 _Py_IDENTIFIER(CANCELLED);
1330 _Py_IDENTIFIER(FINISHED);
1331 PyObject *ret = NULL;
1332
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001333 ENSURE_FUTURE_ALIVE(fut)
1334
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001335 switch (fut->fut_state) {
1336 case STATE_PENDING:
1337 ret = _PyUnicode_FromId(&PyId_PENDING);
1338 break;
1339 case STATE_CANCELLED:
1340 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1341 break;
1342 case STATE_FINISHED:
1343 ret = _PyUnicode_FromId(&PyId_FINISHED);
1344 break;
1345 default:
1346 assert (0);
1347 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001348 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001349 return ret;
1350}
1351
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001352/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001353_asyncio.Future._make_cancelled_error
1354
1355Create the CancelledError to raise if the Future is cancelled.
1356
1357This should only be called once when handling a cancellation since
1358it erases the context exception value.
1359[clinic start generated code]*/
1360
1361static PyObject *
1362_asyncio_Future__make_cancelled_error_impl(FutureObj *self)
1363/*[clinic end generated code: output=a5df276f6c1213de input=ac6effe4ba795ecc]*/
1364{
1365 PyObject *exc = create_cancelled_error(self->fut_cancel_msg);
1366 _PyErr_StackItem *exc_state = &self->fut_cancelled_exc_state;
1367 /* Transfer ownership of exc_value from exc_state to exc since we are
1368 done with it. */
1369 PyException_SetContext(exc, exc_state->exc_value);
1370 exc_state->exc_value = NULL;
1371
1372 return exc;
1373}
1374
1375/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001376_asyncio.Future._repr_info
1377[clinic start generated code]*/
1378
1379static PyObject *
1380_asyncio_Future__repr_info_impl(FutureObj *self)
1381/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001382{
Petr Viktorinffd97532020-02-11 17:46:57 +01001383 return PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001384}
1385
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001386static PyObject *
1387FutureObj_repr(FutureObj *fut)
1388{
1389 _Py_IDENTIFIER(_repr_info);
1390
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001391 ENSURE_FUTURE_ALIVE(fut)
1392
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001393 PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
1394 &PyId__repr_info);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001395 if (rinfo == NULL) {
1396 return NULL;
1397 }
1398
Serhiy Storchakabca49392017-09-03 08:10:14 +03001399 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001400 Py_DECREF(rinfo);
1401 if (rinfo_s == NULL) {
1402 return NULL;
1403 }
1404
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001405 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1406 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001407 Py_DECREF(rinfo_s);
1408 return rstr;
1409}
1410
1411static void
1412FutureObj_finalize(FutureObj *fut)
1413{
1414 _Py_IDENTIFIER(call_exception_handler);
1415 _Py_IDENTIFIER(message);
1416 _Py_IDENTIFIER(exception);
1417 _Py_IDENTIFIER(future);
1418 _Py_IDENTIFIER(source_traceback);
1419
Serhiy Storchakabca49392017-09-03 08:10:14 +03001420 PyObject *error_type, *error_value, *error_traceback;
1421 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001422 PyObject *message = NULL;
1423 PyObject *func;
1424
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001425 if (!fut->fut_log_tb) {
1426 return;
1427 }
1428 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001429 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001430
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001431 /* Save the current exception, if any. */
1432 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1433
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001434 context = PyDict_New();
1435 if (context == NULL) {
1436 goto finally;
1437 }
1438
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001439 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001440 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001441 if (message == NULL) {
1442 goto finally;
1443 }
1444
1445 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1446 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1447 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1448 goto finally;
1449 }
1450 if (fut->fut_source_tb != NULL) {
1451 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1452 fut->fut_source_tb) < 0) {
1453 goto finally;
1454 }
1455 }
1456
1457 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1458 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01001459 PyObject *res = PyObject_CallOneArg(func, context);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001460 if (res == NULL) {
1461 PyErr_WriteUnraisable(func);
1462 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001463 else {
1464 Py_DECREF(res);
1465 }
1466 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001467 }
1468
1469finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001470 Py_XDECREF(context);
1471 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001472
1473 /* Restore the saved exception. */
1474 PyErr_Restore(error_type, error_value, error_traceback);
1475}
1476
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001477static PyObject *
1478future_cls_getitem(PyObject *cls, PyObject *type)
1479{
1480 Py_INCREF(cls);
1481 return cls;
1482}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001483
1484static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001485 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001486 0, /* am_aiter */
1487 0 /* am_anext */
1488};
1489
1490static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001491 _ASYNCIO_FUTURE_RESULT_METHODDEF
1492 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1493 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1494 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1495 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1496 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1497 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1498 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1499 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001500 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001501 _ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001502 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001503 {"__class_getitem__", future_cls_getitem, METH_O|METH_CLASS, NULL},
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001504 {NULL, NULL} /* Sentinel */
1505};
1506
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001507#define FUTURE_COMMON_GETSETLIST \
1508 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1509 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1510 (setter)FutureObj_set_blocking, NULL}, \
1511 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1512 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1513 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1514 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001515 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1516 (setter)FutureObj_set_log_traceback, NULL}, \
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001517 {"_source_traceback", (getter)FutureObj_get_source_traceback, \
1518 NULL, NULL}, \
1519 {"_cancel_message", (getter)FutureObj_get_cancel_message, \
1520 (setter)FutureObj_set_cancel_message, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001521
1522static PyGetSetDef FutureType_getsetlist[] = {
1523 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001524 {NULL} /* Sentinel */
1525};
1526
1527static void FutureObj_dealloc(PyObject *self);
1528
1529static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001530 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001531 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001532 sizeof(FutureObj), /* tp_basicsize */
1533 .tp_dealloc = FutureObj_dealloc,
1534 .tp_as_async = &FutureType_as_async,
1535 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001536 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001537 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001538 .tp_traverse = (traverseproc)FutureObj_traverse,
1539 .tp_clear = (inquiry)FutureObj_clear,
1540 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001541 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001542 .tp_methods = FutureType_methods,
1543 .tp_getset = FutureType_getsetlist,
1544 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001545 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001546 .tp_new = PyType_GenericNew,
1547 .tp_finalize = (destructor)FutureObj_finalize,
1548};
1549
1550static void
1551FutureObj_dealloc(PyObject *self)
1552{
1553 FutureObj *fut = (FutureObj *)self;
1554
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001555 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001556 /* When fut is subclass of Future, finalizer is called from
1557 * subtype_dealloc.
1558 */
1559 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1560 // resurrected.
1561 return;
1562 }
1563 }
1564
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001565 PyObject_GC_UnTrack(self);
1566
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001567 if (fut->fut_weakreflist != NULL) {
1568 PyObject_ClearWeakRefs(self);
1569 }
1570
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001571 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001572 Py_TYPE(fut)->tp_free(fut);
1573}
1574
1575
1576/*********************** Future Iterator **************************/
1577
1578typedef struct {
1579 PyObject_HEAD
1580 FutureObj *future;
1581} futureiterobject;
1582
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001583
1584#define FI_FREELIST_MAXLEN 255
1585static futureiterobject *fi_freelist = NULL;
1586static Py_ssize_t fi_freelist_len = 0;
1587
1588
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001589static void
1590FutureIter_dealloc(futureiterobject *it)
1591{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001592 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001593 Py_CLEAR(it->future);
1594
1595 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1596 fi_freelist_len++;
1597 it->future = (FutureObj*) fi_freelist;
1598 fi_freelist = it;
1599 }
1600 else {
1601 PyObject_GC_Del(it);
1602 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001603}
1604
1605static PyObject *
1606FutureIter_iternext(futureiterobject *it)
1607{
1608 PyObject *res;
1609 FutureObj *fut = it->future;
1610
1611 if (fut == NULL) {
1612 return NULL;
1613 }
1614
1615 if (fut->fut_state == STATE_PENDING) {
1616 if (!fut->fut_blocking) {
1617 fut->fut_blocking = 1;
1618 Py_INCREF(fut);
1619 return (PyObject *)fut;
1620 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001621 PyErr_SetString(PyExc_RuntimeError,
1622 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001623 return NULL;
1624 }
1625
Serhiy Storchakabca49392017-09-03 08:10:14 +03001626 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001627 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001628 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001629 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001630 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001631 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001632 }
1633
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001634 Py_DECREF(fut);
1635 return NULL;
1636}
1637
1638static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001639FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001640{
INADA Naoki74c17532016-10-25 19:00:45 +09001641 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001642 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001643 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001644 return FutureIter_iternext(self);
1645}
1646
1647static PyObject *
1648FutureIter_throw(futureiterobject *self, PyObject *args)
1649{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001650 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001651 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1652 return NULL;
1653
1654 if (val == Py_None) {
1655 val = NULL;
1656 }
1657 if (tb == Py_None) {
1658 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001659 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1660 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1661 return NULL;
1662 }
1663
1664 Py_INCREF(type);
1665 Py_XINCREF(val);
1666 Py_XINCREF(tb);
1667
1668 if (PyExceptionClass_Check(type)) {
1669 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001670 /* No need to call PyException_SetTraceback since we'll be calling
1671 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001672 } else if (PyExceptionInstance_Check(type)) {
1673 if (val) {
1674 PyErr_SetString(PyExc_TypeError,
1675 "instance exception may not have a separate value");
1676 goto fail;
1677 }
1678 val = type;
1679 type = PyExceptionInstance_Class(type);
1680 Py_INCREF(type);
1681 if (tb == NULL)
1682 tb = PyException_GetTraceback(val);
1683 } else {
1684 PyErr_SetString(PyExc_TypeError,
1685 "exceptions must be classes deriving BaseException or "
1686 "instances of such a class");
1687 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001688 }
1689
1690 Py_CLEAR(self->future);
1691
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001692 PyErr_Restore(type, val, tb);
1693
Serhiy Storchakabca49392017-09-03 08:10:14 +03001694 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001695
1696 fail:
1697 Py_DECREF(type);
1698 Py_XDECREF(val);
1699 Py_XDECREF(tb);
1700 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001701}
1702
1703static PyObject *
1704FutureIter_close(futureiterobject *self, PyObject *arg)
1705{
1706 Py_CLEAR(self->future);
1707 Py_RETURN_NONE;
1708}
1709
1710static int
1711FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1712{
1713 Py_VISIT(it->future);
1714 return 0;
1715}
1716
1717static PyMethodDef FutureIter_methods[] = {
1718 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1719 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1720 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1721 {NULL, NULL} /* Sentinel */
1722};
1723
1724static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001725 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001726 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001727 .tp_basicsize = sizeof(futureiterobject),
1728 .tp_itemsize = 0,
1729 .tp_dealloc = (destructor)FutureIter_dealloc,
1730 .tp_getattro = PyObject_GenericGetAttr,
1731 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1732 .tp_traverse = (traverseproc)FutureIter_traverse,
1733 .tp_iter = PyObject_SelfIter,
1734 .tp_iternext = (iternextfunc)FutureIter_iternext,
1735 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001736};
1737
1738static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001739future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001740{
1741 futureiterobject *it;
1742
1743 if (!PyObject_TypeCheck(fut, &FutureType)) {
1744 PyErr_BadInternalCall();
1745 return NULL;
1746 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001747
1748 ENSURE_FUTURE_ALIVE(fut)
1749
1750 if (fi_freelist_len) {
1751 fi_freelist_len--;
1752 it = fi_freelist;
1753 fi_freelist = (futureiterobject*) it->future;
1754 it->future = NULL;
1755 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001756 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001757 else {
1758 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1759 if (it == NULL) {
1760 return NULL;
1761 }
1762 }
1763
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001764 Py_INCREF(fut);
1765 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001766 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001767 return (PyObject*)it;
1768}
1769
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001770
1771/*********************** Task **************************/
1772
1773
1774/*[clinic input]
1775class _asyncio.Task "TaskObj *" "&Task_Type"
1776[clinic start generated code]*/
1777/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1778
1779static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001780static PyObject * task_wakeup(TaskObj *, PyObject *);
1781static PyObject * task_step(TaskObj *, PyObject *);
1782
1783/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001784
INADA Naokic411a7d2016-10-18 11:48:14 +09001785static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001786TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001787{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001788 Py_CLEAR(o->sw_task);
1789 Py_CLEAR(o->sw_arg);
1790 return 0;
1791}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001792
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001793static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001794TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001795{
1796 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001797 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001798 Py_TYPE(o)->tp_free(o);
1799}
1800
1801static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001802TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001803 PyObject *args, PyObject *kwds)
1804{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001805 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1806 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1807 return NULL;
1808 }
1809 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1810 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1811 return NULL;
1812 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001813 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001814}
1815
1816static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001817TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001818 visitproc visit, void *arg)
1819{
1820 Py_VISIT(o->sw_task);
1821 Py_VISIT(o->sw_arg);
1822 return 0;
1823}
1824
1825static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001826TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001827{
1828 if (o->sw_task) {
1829 Py_INCREF(o->sw_task);
1830 return (PyObject*)o->sw_task;
1831 }
1832 Py_RETURN_NONE;
1833}
1834
Serhiy Storchakabca49392017-09-03 08:10:14 +03001835static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1836 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001837 {NULL} /* Sentinel */
1838};
1839
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001840static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001841 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001842 "TaskStepMethWrapper",
1843 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001844 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001845 .tp_getset = TaskStepMethWrapper_getsetlist,
1846 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1847 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001848 .tp_getattro = PyObject_GenericGetAttr,
1849 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001850 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1851 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001852};
1853
1854static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001855TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001856{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001857 TaskStepMethWrapper *o;
1858 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001859 if (o == NULL) {
1860 return NULL;
1861 }
1862
1863 Py_INCREF(task);
1864 o->sw_task = task;
1865
1866 Py_XINCREF(arg);
1867 o->sw_arg = arg;
1868
1869 PyObject_GC_Track(o);
1870 return (PyObject*) o;
1871}
1872
1873/* ----- Task._wakeup wrapper */
1874
1875static PyObject *
1876TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1877 PyObject *args, PyObject *kwds)
1878{
1879 PyObject *fut;
1880
Serhiy Storchakabca49392017-09-03 08:10:14 +03001881 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1882 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1883 return NULL;
1884 }
1885 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001886 return NULL;
1887 }
1888
Yury Selivanov22feeb82018-01-24 11:31:01 -05001889 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001890}
1891
1892static int
1893TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1894{
1895 Py_CLEAR(o->ww_task);
1896 return 0;
1897}
1898
1899static int
1900TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1901 visitproc visit, void *arg)
1902{
1903 Py_VISIT(o->ww_task);
1904 return 0;
1905}
1906
1907static void
1908TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1909{
1910 PyObject_GC_UnTrack(o);
1911 (void)TaskWakeupMethWrapper_clear(o);
1912 Py_TYPE(o)->tp_free(o);
1913}
1914
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001915static PyObject *
1916TaskWakeupMethWrapper_get___self__(TaskWakeupMethWrapper *o, void *Py_UNUSED(ignored))
1917{
1918 if (o->ww_task) {
1919 Py_INCREF(o->ww_task);
1920 return (PyObject*)o->ww_task;
1921 }
1922 Py_RETURN_NONE;
1923}
1924
1925static PyGetSetDef TaskWakeupMethWrapper_getsetlist[] = {
1926 {"__self__", (getter)TaskWakeupMethWrapper_get___self__, NULL, NULL},
1927 {NULL} /* Sentinel */
1928};
1929
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001930static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001931 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001932 "TaskWakeupMethWrapper",
1933 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1934 .tp_itemsize = 0,
1935 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1936 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1937 .tp_getattro = PyObject_GenericGetAttr,
1938 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1939 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1940 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001941 .tp_getset = TaskWakeupMethWrapper_getsetlist,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001942};
1943
1944static PyObject *
1945TaskWakeupMethWrapper_new(TaskObj *task)
1946{
1947 TaskWakeupMethWrapper *o;
1948 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1949 if (o == NULL) {
1950 return NULL;
1951 }
1952
1953 Py_INCREF(task);
1954 o->ww_task = task;
1955
1956 PyObject_GC_Track(o);
1957 return (PyObject*) o;
1958}
1959
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001960/* ----- Task introspection helpers */
1961
1962static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001963register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001964{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001965 _Py_IDENTIFIER(add);
1966
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001967 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1968 &PyId_add, task);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001969 if (res == NULL) {
1970 return -1;
1971 }
1972 Py_DECREF(res);
1973 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001974}
1975
1976
1977static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001978unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001979{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001980 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001981
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001982 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1983 &PyId_discard, task);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001984 if (res == NULL) {
1985 return -1;
1986 }
1987 Py_DECREF(res);
1988 return 0;
1989}
1990
1991
1992static int
1993enter_task(PyObject *loop, PyObject *task)
1994{
1995 PyObject *item;
1996 Py_hash_t hash;
1997 hash = PyObject_Hash(loop);
1998 if (hash == -1) {
1999 return -1;
2000 }
2001 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
2002 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002003 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002004 PyErr_Format(
2005 PyExc_RuntimeError,
2006 "Cannot enter into task %R while another " \
2007 "task %R is being executed.",
2008 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002009 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002010 return -1;
2011 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03002012 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002013 return -1;
2014 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03002015 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002016}
2017
2018
2019static int
2020leave_task(PyObject *loop, PyObject *task)
2021/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
2022{
2023 PyObject *item;
2024 Py_hash_t hash;
2025 hash = PyObject_Hash(loop);
2026 if (hash == -1) {
2027 return -1;
2028 }
2029 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
2030 if (item != task) {
2031 if (item == NULL) {
2032 /* Not entered, replace with None */
2033 item = Py_None;
2034 }
2035 PyErr_Format(
2036 PyExc_RuntimeError,
2037 "Leaving task %R does not match the current task %R.",
2038 task, item, NULL);
2039 return -1;
2040 }
2041 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
2042}
2043
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002044/* ----- Task */
2045
2046/*[clinic input]
2047_asyncio.Task.__init__
2048
Serhiy Storchakabca49392017-09-03 08:10:14 +03002049 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002050 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002051 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002052 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002053
2054A coroutine wrapped in a Future.
2055[clinic start generated code]*/
2056
2057static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002058_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2059 PyObject *name)
2060/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002061{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002062 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002063 return -1;
2064 }
INADA Naokic411a7d2016-10-18 11:48:14 +09002065
Yury Selivanova9d7e552017-12-19 07:18:45 -05002066 int is_coro = is_coroutine(coro);
2067 if (is_coro == -1) {
2068 return -1;
2069 }
2070 if (is_coro == 0) {
2071 self->task_log_destroy_pending = 0;
2072 PyErr_Format(PyExc_TypeError,
2073 "a coroutine was expected, got %R",
2074 coro, NULL);
2075 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02002076 }
2077
Oren Milmand019bc82018-02-13 12:28:33 +02002078 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05002079 if (self->task_context == NULL) {
2080 return -1;
2081 }
2082
Oren Milmand019bc82018-02-13 12:28:33 +02002083 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002084 self->task_must_cancel = 0;
2085 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002086 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02002087 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002088
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002089 if (name == Py_None) {
2090 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03002091 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002092 name = PyObject_Str(name);
2093 } else {
2094 Py_INCREF(name);
2095 }
2096 Py_XSETREF(self->task_name, name);
2097 if (self->task_name == NULL) {
2098 return -1;
2099 }
2100
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002101 if (task_call_step_soon(self, NULL)) {
2102 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09002103 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002104 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002105}
2106
2107static int
2108TaskObj_clear(TaskObj *task)
2109{
2110 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002111 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002112 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002113 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002114 Py_CLEAR(task->task_fut_waiter);
2115 return 0;
2116}
2117
2118static int
2119TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2120{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002121 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002122 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002123 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002124 Py_VISIT(task->task_fut_waiter);
2125 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2126 return 0;
2127}
2128
2129static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002130TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002131{
2132 if (task->task_log_destroy_pending) {
2133 Py_RETURN_TRUE;
2134 }
2135 else {
2136 Py_RETURN_FALSE;
2137 }
2138}
2139
2140static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002141TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002142{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002143 if (val == NULL) {
2144 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2145 return -1;
2146 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002147 int is_true = PyObject_IsTrue(val);
2148 if (is_true < 0) {
2149 return -1;
2150 }
2151 task->task_log_destroy_pending = is_true;
2152 return 0;
2153}
2154
2155static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002156TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002157{
2158 if (task->task_must_cancel) {
2159 Py_RETURN_TRUE;
2160 }
2161 else {
2162 Py_RETURN_FALSE;
2163 }
2164}
2165
2166static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002167TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002168{
2169 if (task->task_coro) {
2170 Py_INCREF(task->task_coro);
2171 return task->task_coro;
2172 }
2173
2174 Py_RETURN_NONE;
2175}
2176
2177static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002178TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002179{
2180 if (task->task_fut_waiter) {
2181 Py_INCREF(task->task_fut_waiter);
2182 return task->task_fut_waiter;
2183 }
2184
2185 Py_RETURN_NONE;
2186}
2187
2188/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002189_asyncio.Task._make_cancelled_error
2190
2191Create the CancelledError to raise if the Task is cancelled.
2192
2193This should only be called once when handling a cancellation since
2194it erases the context exception value.
2195[clinic start generated code]*/
2196
2197static PyObject *
2198_asyncio_Task__make_cancelled_error_impl(TaskObj *self)
2199/*[clinic end generated code: output=55a819e8b4276fab input=52c0e32de8e2f840]*/
2200{
2201 FutureObj *fut = (FutureObj*)self;
2202 return _asyncio_Future__make_cancelled_error_impl(fut);
2203}
2204
2205
2206/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002207_asyncio.Task._repr_info
2208[clinic start generated code]*/
2209
2210static PyObject *
2211_asyncio_Task__repr_info_impl(TaskObj *self)
2212/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2213{
Petr Viktorinffd97532020-02-11 17:46:57 +01002214 return PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002215}
2216
2217/*[clinic input]
2218_asyncio.Task.cancel
2219
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002220 msg: object = None
2221
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002222Request that this task cancel itself.
2223
2224This arranges for a CancelledError to be thrown into the
2225wrapped coroutine on the next cycle through the event loop.
2226The coroutine then has a chance to clean up or even deny
2227the request using try/except/finally.
2228
2229Unlike Future.cancel, this does not guarantee that the
2230task will be cancelled: the exception might be caught and
2231acted upon, delaying cancellation of the task or preventing
2232cancellation completely. The task may also return a value or
2233raise a different exception.
2234
2235Immediately after this method is called, Task.cancelled() will
2236not return True (unless the task was already cancelled). A
2237task will be marked as cancelled when the wrapped coroutine
2238terminates with a CancelledError exception (even if cancel()
2239was not called).
2240[clinic start generated code]*/
2241
2242static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002243_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
2244/*[clinic end generated code: output=c66b60d41c74f9f1 input=f4ff8e8ffc5f1c00]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002245{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002246 self->task_log_tb = 0;
2247
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002248 if (self->task_state != STATE_PENDING) {
2249 Py_RETURN_FALSE;
2250 }
2251
2252 if (self->task_fut_waiter) {
2253 PyObject *res;
2254 int is_true;
2255
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002256 res = _PyObject_CallMethodIdOneArg(self->task_fut_waiter,
2257 &PyId_cancel, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002258 if (res == NULL) {
2259 return NULL;
2260 }
2261
2262 is_true = PyObject_IsTrue(res);
2263 Py_DECREF(res);
2264 if (is_true < 0) {
2265 return NULL;
2266 }
2267
2268 if (is_true) {
2269 Py_RETURN_TRUE;
2270 }
2271 }
2272
2273 self->task_must_cancel = 1;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002274 Py_XINCREF(msg);
2275 Py_XSETREF(self->task_cancel_msg, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002276 Py_RETURN_TRUE;
2277}
2278
2279/*[clinic input]
2280_asyncio.Task.get_stack
2281
2282 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002283 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002284
2285Return the list of stack frames for this task's coroutine.
2286
2287If the coroutine is not done, this returns the stack where it is
2288suspended. If the coroutine has completed successfully or was
2289cancelled, this returns an empty list. If the coroutine was
2290terminated by an exception, this returns the list of traceback
2291frames.
2292
2293The frames are always ordered from oldest to newest.
2294
2295The optional limit gives the maximum number of frames to
2296return; by default all available frames are returned. Its
2297meaning differs depending on whether a stack or a traceback is
2298returned: the newest frames of a stack are returned, but the
2299oldest frames of a traceback are returned. (This matches the
2300behavior of the traceback module.)
2301
2302For reasons beyond our control, only one stack frame is
2303returned for a suspended coroutine.
2304[clinic start generated code]*/
2305
2306static PyObject *
2307_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002308/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002309{
2310 return PyObject_CallFunctionObjArgs(
2311 asyncio_task_get_stack_func, self, limit, NULL);
2312}
2313
2314/*[clinic input]
2315_asyncio.Task.print_stack
2316
2317 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002318 limit: object = None
2319 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002320
2321Print the stack or traceback for this task's coroutine.
2322
2323This produces output similar to that of the traceback module,
2324for the frames retrieved by get_stack(). The limit argument
2325is passed to get_stack(). The file argument is an I/O stream
2326to which the output is written; by default output is written
2327to sys.stderr.
2328[clinic start generated code]*/
2329
2330static PyObject *
2331_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2332 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002333/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002334{
2335 return PyObject_CallFunctionObjArgs(
2336 asyncio_task_print_stack_func, self, limit, file, NULL);
2337}
2338
2339/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002340_asyncio.Task.set_result
2341
2342 result: object
2343 /
2344[clinic start generated code]*/
2345
2346static PyObject *
2347_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2348/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2349{
2350 PyErr_SetString(PyExc_RuntimeError,
2351 "Task does not support set_result operation");
2352 return NULL;
2353}
2354
2355/*[clinic input]
2356_asyncio.Task.set_exception
2357
2358 exception: object
2359 /
2360[clinic start generated code]*/
2361
2362static PyObject *
2363_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2364/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2365{
2366 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002367 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002368 return NULL;
2369}
2370
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002371/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002372_asyncio.Task.get_coro
2373[clinic start generated code]*/
2374
2375static PyObject *
2376_asyncio_Task_get_coro_impl(TaskObj *self)
2377/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2378{
2379 Py_INCREF(self->task_coro);
2380 return self->task_coro;
2381}
2382
2383/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002384_asyncio.Task.get_name
2385[clinic start generated code]*/
2386
2387static PyObject *
2388_asyncio_Task_get_name_impl(TaskObj *self)
2389/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2390{
2391 if (self->task_name) {
2392 Py_INCREF(self->task_name);
2393 return self->task_name;
2394 }
2395
2396 Py_RETURN_NONE;
2397}
2398
2399/*[clinic input]
2400_asyncio.Task.set_name
2401
2402 value: object
2403 /
2404[clinic start generated code]*/
2405
2406static PyObject *
2407_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2408/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2409{
Alex Grönholma7548232018-08-09 23:49:49 +03002410 if (!PyUnicode_CheckExact(value)) {
2411 value = PyObject_Str(value);
2412 if (value == NULL) {
2413 return NULL;
2414 }
2415 } else {
2416 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002417 }
2418
Alex Grönholma7548232018-08-09 23:49:49 +03002419 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002420 Py_RETURN_NONE;
2421}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002422
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002423static void
2424TaskObj_finalize(TaskObj *task)
2425{
2426 _Py_IDENTIFIER(call_exception_handler);
2427 _Py_IDENTIFIER(task);
2428 _Py_IDENTIFIER(message);
2429 _Py_IDENTIFIER(source_traceback);
2430
Serhiy Storchakabca49392017-09-03 08:10:14 +03002431 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002432 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002433 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002434 PyObject *error_type, *error_value, *error_traceback;
2435
2436 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2437 goto done;
2438 }
2439
2440 /* Save the current exception, if any. */
2441 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2442
2443 context = PyDict_New();
2444 if (context == NULL) {
2445 goto finally;
2446 }
2447
2448 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2449 if (message == NULL) {
2450 goto finally;
2451 }
2452
2453 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2454 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2455 {
2456 goto finally;
2457 }
2458
2459 if (task->task_source_tb != NULL) {
2460 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2461 task->task_source_tb) < 0)
2462 {
2463 goto finally;
2464 }
2465 }
2466
2467 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2468 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01002469 PyObject *res = PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002470 if (res == NULL) {
2471 PyErr_WriteUnraisable(func);
2472 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002473 else {
2474 Py_DECREF(res);
2475 }
2476 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002477 }
2478
2479finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002480 Py_XDECREF(context);
2481 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002482
2483 /* Restore the saved exception. */
2484 PyErr_Restore(error_type, error_value, error_traceback);
2485
2486done:
2487 FutureObj_finalize((FutureObj*)task);
2488}
2489
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002490static PyObject *
2491task_cls_getitem(PyObject *cls, PyObject *type)
2492{
2493 Py_INCREF(cls);
2494 return cls;
2495}
2496
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002497static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2498
2499static PyMethodDef TaskType_methods[] = {
2500 _ASYNCIO_FUTURE_RESULT_METHODDEF
2501 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002502 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2503 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2504 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2505 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002506 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2507 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002508 _ASYNCIO_TASK_CANCEL_METHODDEF
2509 _ASYNCIO_TASK_GET_STACK_METHODDEF
2510 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002511 _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002512 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002513 _ASYNCIO_TASK_GET_NAME_METHODDEF
2514 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002515 _ASYNCIO_TASK_GET_CORO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002516 {"__class_getitem__", task_cls_getitem, METH_O|METH_CLASS, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002517 {NULL, NULL} /* Sentinel */
2518};
2519
2520static PyGetSetDef TaskType_getsetlist[] = {
2521 FUTURE_COMMON_GETSETLIST
2522 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2523 (setter)TaskObj_set_log_destroy_pending, NULL},
2524 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2525 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2526 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2527 {NULL} /* Sentinel */
2528};
2529
2530static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002531 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002532 "_asyncio.Task",
2533 sizeof(TaskObj), /* tp_basicsize */
2534 .tp_base = &FutureType,
2535 .tp_dealloc = TaskObj_dealloc,
2536 .tp_as_async = &FutureType_as_async,
2537 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002538 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002539 .tp_doc = _asyncio_Task___init____doc__,
2540 .tp_traverse = (traverseproc)TaskObj_traverse,
2541 .tp_clear = (inquiry)TaskObj_clear,
2542 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2543 .tp_iter = (getiterfunc)future_new_iter,
2544 .tp_methods = TaskType_methods,
2545 .tp_getset = TaskType_getsetlist,
2546 .tp_dictoffset = offsetof(TaskObj, dict),
2547 .tp_init = (initproc)_asyncio_Task___init__,
2548 .tp_new = PyType_GenericNew,
2549 .tp_finalize = (destructor)TaskObj_finalize,
2550};
2551
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002552static void
2553TaskObj_dealloc(PyObject *self)
2554{
2555 TaskObj *task = (TaskObj *)self;
2556
2557 if (Task_CheckExact(self)) {
2558 /* When fut is subclass of Task, finalizer is called from
2559 * subtype_dealloc.
2560 */
2561 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2562 // resurrected.
2563 return;
2564 }
2565 }
2566
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002567 PyObject_GC_UnTrack(self);
2568
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002569 if (task->task_weakreflist != NULL) {
2570 PyObject_ClearWeakRefs(self);
2571 }
2572
2573 (void)TaskObj_clear(task);
2574 Py_TYPE(task)->tp_free(task);
2575}
2576
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002577static int
2578task_call_step_soon(TaskObj *task, PyObject *arg)
2579{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002580 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002581 if (cb == NULL) {
2582 return -1;
2583 }
2584
Yury Selivanovf23746a2018-01-22 19:11:18 -05002585 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002586 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002587 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002588}
2589
2590static PyObject *
2591task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2592{
2593 PyObject* msg;
2594
2595 va_list vargs;
2596#ifdef HAVE_STDARG_PROTOTYPES
2597 va_start(vargs, format);
2598#else
2599 va_start(vargs);
2600#endif
2601 msg = PyUnicode_FromFormatV(format, vargs);
2602 va_end(vargs);
2603
2604 if (msg == NULL) {
2605 return NULL;
2606 }
2607
Petr Viktorinffd97532020-02-11 17:46:57 +01002608 PyObject *e = PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002609 Py_DECREF(msg);
2610 if (e == NULL) {
2611 return NULL;
2612 }
2613
2614 if (task_call_step_soon(task, e) == -1) {
2615 Py_DECREF(e);
2616 return NULL;
2617 }
2618
2619 Py_DECREF(e);
2620 Py_RETURN_NONE;
2621}
2622
2623static PyObject *
2624task_step_impl(TaskObj *task, PyObject *exc)
2625{
2626 int res;
2627 int clear_exc = 0;
2628 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002629 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002630 PyObject *o;
2631
2632 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002633 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002634 "_step(): already done: %R %R",
2635 task,
2636 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002637 goto fail;
2638 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002639
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002640 if (task->task_must_cancel) {
2641 assert(exc != Py_None);
2642
2643 if (exc) {
2644 /* Check if exc is a CancelledError */
2645 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2646 if (res == -1) {
2647 /* An error occurred, abort */
2648 goto fail;
2649 }
2650 if (res == 0) {
2651 /* exc is not CancelledError; reset it to NULL */
2652 exc = NULL;
2653 }
2654 }
2655
2656 if (!exc) {
2657 /* exc was not a CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002658 exc = create_cancelled_error(task->task_cancel_msg);
2659
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002660 if (!exc) {
2661 goto fail;
2662 }
2663 clear_exc = 1;
2664 }
2665
2666 task->task_must_cancel = 0;
2667 }
2668
2669 Py_CLEAR(task->task_fut_waiter);
2670
Serhiy Storchakabca49392017-09-03 08:10:14 +03002671 coro = task->task_coro;
2672 if (coro == NULL) {
2673 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
Chris Jerdonekd2c349b2020-05-08 03:54:38 -07002674 if (clear_exc) {
2675 /* We created 'exc' during this call */
2676 Py_DECREF(exc);
2677 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002678 return NULL;
2679 }
2680
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002681 if (exc == NULL) {
2682 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2683 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2684 }
2685 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002686 result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002687 }
2688 }
2689 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002690 result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002691 if (clear_exc) {
2692 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002693 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002694 }
2695 }
2696
2697 if (result == NULL) {
2698 PyObject *et, *ev, *tb;
2699
2700 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2701 /* The error is StopIteration and that means that
2702 the underlying coroutine has resolved */
Yury Selivanovedad4d82019-09-25 03:32:08 -07002703
2704 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002705 if (task->task_must_cancel) {
2706 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002707 task->task_must_cancel = 0;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002708 res = future_cancel((FutureObj*)task, task->task_cancel_msg);
INADA Naoki991adca2017-05-11 21:18:38 +09002709 }
Yury Selivanovedad4d82019-09-25 03:32:08 -07002710 else {
2711 res = future_set_result((FutureObj*)task, o);
2712 }
2713
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002714 Py_DECREF(o);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002715
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002716 if (res == NULL) {
2717 return NULL;
2718 }
2719 Py_DECREF(res);
2720 Py_RETURN_NONE;
2721 }
2722
2723 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2724 /* CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002725 PyErr_Fetch(&et, &ev, &tb);
2726
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002727 FutureObj *fut = (FutureObj*)task;
2728 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
2729 exc_state->exc_type = et;
2730 exc_state->exc_value = ev;
2731 exc_state->exc_traceback = tb;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002732
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002733 return future_cancel(fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002734 }
2735
2736 /* Some other exception; pop it and call Task.set_exception() */
2737 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002738
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002739 assert(et);
2740 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2741 PyErr_NormalizeException(&et, &ev, &tb);
2742 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002743 if (tb != NULL) {
2744 PyException_SetTraceback(ev, tb);
2745 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002746 o = future_set_exception((FutureObj*)task, ev);
2747 if (!o) {
2748 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002749 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002750 Py_XDECREF(tb);
2751 Py_XDECREF(ev);
2752 goto fail;
2753 }
2754 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002755 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002756
Yury Selivanov431b5402019-05-27 14:45:12 +02002757 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2758 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2759 {
2760 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002761 PyErr_Restore(et, ev, tb);
2762 goto fail;
2763 }
2764
Serhiy Storchakabca49392017-09-03 08:10:14 +03002765 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002766 Py_XDECREF(tb);
2767 Py_XDECREF(ev);
2768
2769 Py_RETURN_NONE;
2770 }
2771
2772 if (result == (PyObject*)task) {
2773 /* We have a task that wants to await on itself */
2774 goto self_await;
2775 }
2776
2777 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2778 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2779 PyObject *wrapper;
2780 PyObject *res;
2781 FutureObj *fut = (FutureObj*)result;
2782
2783 /* Check if `result` future is attached to a different loop */
2784 if (fut->fut_loop != task->task_loop) {
2785 goto different_loop;
2786 }
2787
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002788 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002789 goto yield_insteadof_yf;
2790 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002791
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002792 fut->fut_blocking = 0;
2793
2794 /* result.add_done_callback(task._wakeup) */
2795 wrapper = TaskWakeupMethWrapper_new(task);
2796 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002797 goto fail;
2798 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002799 res = future_add_done_callback(
2800 (FutureObj*)result, wrapper, task->task_context);
2801 Py_DECREF(wrapper);
2802 if (res == NULL) {
2803 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002804 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002805 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002806
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002807 /* task._fut_waiter = result */
2808 task->task_fut_waiter = result; /* no incref is necessary */
2809
2810 if (task->task_must_cancel) {
2811 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002812 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002813 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2814 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002815 if (r == NULL) {
2816 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002817 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002818 is_true = PyObject_IsTrue(r);
2819 Py_DECREF(r);
2820 if (is_true < 0) {
2821 return NULL;
2822 }
2823 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002824 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002825 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002826 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002827
2828 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002829 }
2830
2831 /* Check if `result` is None */
2832 if (result == Py_None) {
2833 /* Bare yield relinquishes control for one event loop iteration. */
2834 if (task_call_step_soon(task, NULL)) {
2835 goto fail;
2836 }
2837 return result;
2838 }
2839
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002840 /* Check if `result` is a Future-compatible object */
2841 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2842 goto fail;
2843 }
2844 if (o != NULL && o != Py_None) {
2845 /* `result` is a Future-compatible object */
2846 PyObject *wrapper;
2847 PyObject *res;
2848
2849 int blocking = PyObject_IsTrue(o);
2850 Py_DECREF(o);
2851 if (blocking < 0) {
2852 goto fail;
2853 }
2854
2855 /* Check if `result` future is attached to a different loop */
2856 PyObject *oloop = get_future_loop(result);
2857 if (oloop == NULL) {
2858 goto fail;
2859 }
2860 if (oloop != task->task_loop) {
2861 Py_DECREF(oloop);
2862 goto different_loop;
2863 }
2864 Py_DECREF(oloop);
2865
2866 if (!blocking) {
2867 goto yield_insteadof_yf;
2868 }
2869
2870 /* result._asyncio_future_blocking = False */
2871 if (_PyObject_SetAttrId(
2872 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2873 goto fail;
2874 }
2875
2876 wrapper = TaskWakeupMethWrapper_new(task);
2877 if (wrapper == NULL) {
2878 goto fail;
2879 }
2880
2881 /* result.add_done_callback(task._wakeup) */
2882 PyObject *add_cb = _PyObject_GetAttrId(
2883 result, &PyId_add_done_callback);
2884 if (add_cb == NULL) {
2885 Py_DECREF(wrapper);
2886 goto fail;
2887 }
2888 PyObject *stack[2];
2889 stack[0] = wrapper;
2890 stack[1] = (PyObject *)task->task_context;
Petr Viktorinffd97532020-02-11 17:46:57 +01002891 res = PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002892 Py_DECREF(add_cb);
2893 Py_DECREF(wrapper);
2894 if (res == NULL) {
2895 goto fail;
2896 }
2897 Py_DECREF(res);
2898
2899 /* task._fut_waiter = result */
2900 task->task_fut_waiter = result; /* no incref is necessary */
2901
2902 if (task->task_must_cancel) {
2903 PyObject *r;
2904 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002905 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2906 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002907 if (r == NULL) {
2908 return NULL;
2909 }
2910 is_true = PyObject_IsTrue(r);
2911 Py_DECREF(r);
2912 if (is_true < 0) {
2913 return NULL;
2914 }
2915 else if (is_true) {
2916 task->task_must_cancel = 0;
2917 }
2918 }
2919
2920 Py_RETURN_NONE;
2921 }
2922
2923 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002924 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002925 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2926 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002927 goto fail;
2928 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002929 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002930 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002931 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002932 task, PyExc_RuntimeError,
2933 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002934 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002935 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002936 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002937 }
2938
2939 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002940 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002941 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002942 Py_DECREF(result);
2943 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002944
2945self_await:
2946 o = task_set_error_soon(
2947 task, PyExc_RuntimeError,
2948 "Task cannot await on itself: %R", task);
2949 Py_DECREF(result);
2950 return o;
2951
2952yield_insteadof_yf:
2953 o = task_set_error_soon(
2954 task, PyExc_RuntimeError,
2955 "yield was used instead of yield from "
2956 "in task %R with %R",
2957 task, result);
2958 Py_DECREF(result);
2959 return o;
2960
2961different_loop:
2962 o = task_set_error_soon(
2963 task, PyExc_RuntimeError,
2964 "Task %R got Future %R attached to a different loop",
2965 task, result);
2966 Py_DECREF(result);
2967 return o;
2968
2969fail:
2970 Py_XDECREF(result);
2971 return NULL;
2972}
2973
2974static PyObject *
2975task_step(TaskObj *task, PyObject *exc)
2976{
2977 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002978
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002979 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002980 return NULL;
2981 }
2982
2983 res = task_step_impl(task, exc);
2984
2985 if (res == NULL) {
2986 PyObject *et, *ev, *tb;
2987 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002988 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002989 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002990 return NULL;
2991 }
2992 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002993 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002994 Py_DECREF(res);
2995 return NULL;
2996 }
2997 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002998 return res;
2999 }
3000 }
3001}
3002
3003static PyObject *
3004task_wakeup(TaskObj *task, PyObject *o)
3005{
Serhiy Storchakabca49392017-09-03 08:10:14 +03003006 PyObject *et, *ev, *tb;
3007 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003008 assert(o);
3009
3010 if (Future_CheckExact(o) || Task_CheckExact(o)) {
3011 PyObject *fut_result = NULL;
3012 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003013
3014 switch(res) {
3015 case -1:
3016 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003017 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003018 case 0:
3019 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003020 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003021 default:
3022 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003023 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003024 Py_DECREF(fut_result);
3025 return result;
3026 }
3027 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003028 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03003029 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
3030 if (fut_result != NULL) {
3031 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003032 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003033 }
3034 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003035 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003036
3037 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003038 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
3039 PyErr_NormalizeException(&et, &ev, &tb);
3040 }
3041
Yury Selivanov22feeb82018-01-24 11:31:01 -05003042 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003043
3044 Py_DECREF(et);
3045 Py_XDECREF(tb);
3046 Py_XDECREF(ev);
3047
3048 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003049}
3050
3051
Yury Selivanova70232f2017-12-13 14:49:42 -05003052/*********************** Functions **************************/
3053
3054
3055/*[clinic input]
3056_asyncio._get_running_loop
3057
3058Return the running event loop or None.
3059
3060This is a low-level function intended to be used by event loops.
3061This function is thread-specific.
3062
3063[clinic start generated code]*/
3064
3065static PyObject *
3066_asyncio__get_running_loop_impl(PyObject *module)
3067/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3068{
3069 PyObject *loop;
3070 if (get_running_loop(&loop)) {
3071 return NULL;
3072 }
3073 if (loop == NULL) {
3074 /* There's no currently running event loop */
3075 Py_RETURN_NONE;
3076 }
3077 return loop;
3078}
3079
3080/*[clinic input]
3081_asyncio._set_running_loop
3082 loop: 'O'
3083 /
3084
3085Set the running event loop.
3086
3087This is a low-level function intended to be used by event loops.
3088This function is thread-specific.
3089[clinic start generated code]*/
3090
3091static PyObject *
3092_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3093/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3094{
3095 if (set_running_loop(loop)) {
3096 return NULL;
3097 }
3098 Py_RETURN_NONE;
3099}
3100
3101/*[clinic input]
3102_asyncio.get_event_loop
3103
3104Return an asyncio event loop.
3105
3106When called from a coroutine or a callback (e.g. scheduled with
3107call_soon or similar API), this function will always return the
3108running event loop.
3109
3110If there is no running event loop set, the function will return
3111the result of `get_event_loop_policy().get_event_loop()` call.
3112[clinic start generated code]*/
3113
3114static PyObject *
3115_asyncio_get_event_loop_impl(PyObject *module)
3116/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3117{
3118 return get_event_loop();
3119}
3120
3121/*[clinic input]
3122_asyncio.get_running_loop
3123
3124Return the running event loop. Raise a RuntimeError if there is none.
3125
3126This function is thread-specific.
3127[clinic start generated code]*/
3128
3129static PyObject *
3130_asyncio_get_running_loop_impl(PyObject *module)
3131/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3132{
3133 PyObject *loop;
3134 if (get_running_loop(&loop)) {
3135 return NULL;
3136 }
3137 if (loop == NULL) {
3138 /* There's no currently running event loop */
3139 PyErr_SetString(
3140 PyExc_RuntimeError, "no running event loop");
3141 }
3142 return loop;
3143}
3144
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003145/*[clinic input]
3146_asyncio._register_task
3147
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003148 task: object
3149
3150Register a new task in asyncio as executed by loop.
3151
3152Returns None.
3153[clinic start generated code]*/
3154
3155static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003156_asyncio__register_task_impl(PyObject *module, PyObject *task)
3157/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003158{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003159 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003160 return NULL;
3161 }
3162 Py_RETURN_NONE;
3163}
3164
3165
3166/*[clinic input]
3167_asyncio._unregister_task
3168
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003169 task: object
3170
3171Unregister a task.
3172
3173Returns None.
3174[clinic start generated code]*/
3175
3176static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003177_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3178/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003179{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003180 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003181 return NULL;
3182 }
3183 Py_RETURN_NONE;
3184}
3185
3186
3187/*[clinic input]
3188_asyncio._enter_task
3189
3190 loop: object
3191 task: object
3192
3193Enter into task execution or resume suspended task.
3194
3195Task belongs to loop.
3196
3197Returns None.
3198[clinic start generated code]*/
3199
3200static PyObject *
3201_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3202/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3203{
3204 if (enter_task(loop, task) < 0) {
3205 return NULL;
3206 }
3207 Py_RETURN_NONE;
3208}
3209
3210
3211/*[clinic input]
3212_asyncio._leave_task
3213
3214 loop: object
3215 task: object
3216
3217Leave task execution or suspend a task.
3218
3219Task belongs to loop.
3220
3221Returns None.
3222[clinic start generated code]*/
3223
3224static PyObject *
3225_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3226/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3227{
3228 if (leave_task(loop, task) < 0) {
3229 return NULL;
3230 }
3231 Py_RETURN_NONE;
3232}
3233
Yury Selivanova70232f2017-12-13 14:49:42 -05003234
Yury Selivanov9d411c12018-01-23 15:10:03 -05003235/*********************** PyRunningLoopHolder ********************/
3236
3237
3238static PyRunningLoopHolder *
3239new_running_loop_holder(PyObject *loop)
3240{
3241 PyRunningLoopHolder *rl = PyObject_New(
3242 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3243 if (rl == NULL) {
3244 return NULL;
3245 }
3246
3247#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3248 rl->rl_pid = getpid();
3249#endif
3250
3251 Py_INCREF(loop);
3252 rl->rl_loop = loop;
3253
3254 return rl;
3255}
3256
3257
3258static void
3259PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3260{
3261 Py_CLEAR(rl->rl_loop);
3262 PyObject_Free(rl);
3263}
3264
3265
3266static PyTypeObject PyRunningLoopHolder_Type = {
3267 PyVarObject_HEAD_INIT(NULL, 0)
3268 "_RunningLoopHolder",
3269 sizeof(PyRunningLoopHolder),
3270 .tp_getattro = PyObject_GenericGetAttr,
3271 .tp_flags = Py_TPFLAGS_DEFAULT,
3272 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3273};
3274
3275
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003276/*********************** Module **************************/
3277
3278
3279static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003280module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003281{
3282 PyObject *next;
3283 PyObject *current;
3284
3285 next = (PyObject*) fi_freelist;
3286 while (next != NULL) {
3287 assert(fi_freelist_len > 0);
3288 fi_freelist_len--;
3289
3290 current = next;
3291 next = (PyObject*) ((futureiterobject*) current)->future;
3292 PyObject_GC_Del(current);
3293 }
3294 assert(fi_freelist_len == 0);
3295 fi_freelist = NULL;
3296}
3297
3298
3299static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003300module_free(void *m)
3301{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003302 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003303 Py_CLEAR(traceback_extract_stack);
3304 Py_CLEAR(asyncio_future_repr_info_func);
3305 Py_CLEAR(asyncio_get_event_loop_policy);
3306 Py_CLEAR(asyncio_iscoroutine_func);
3307 Py_CLEAR(asyncio_task_get_stack_func);
3308 Py_CLEAR(asyncio_task_print_stack_func);
3309 Py_CLEAR(asyncio_task_repr_info_func);
3310 Py_CLEAR(asyncio_InvalidStateError);
3311 Py_CLEAR(asyncio_CancelledError);
3312
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003313 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003314 Py_CLEAR(current_tasks);
3315 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003316
Yury Selivanovf23746a2018-01-22 19:11:18 -05003317 Py_CLEAR(context_kwname);
3318
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003319 module_free_freelists();
Jeffrey Quesnellea75e7302020-04-16 22:09:45 -04003320
3321 module_initialized = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003322}
3323
3324static int
3325module_init(void)
3326{
3327 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003328
3329 asyncio_mod = PyImport_ImportModule("asyncio");
3330 if (asyncio_mod == NULL) {
3331 goto fail;
3332 }
Ben Harper321def82019-10-07 12:19:58 -04003333 if (module_initialized != 0) {
3334 return 0;
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02003335 }
Ben Harper321def82019-10-07 12:19:58 -04003336 else {
3337 module_initialized = 1;
3338 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003339
3340 current_tasks = PyDict_New();
3341 if (current_tasks == NULL) {
3342 goto fail;
3343 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003344
Yury Selivanova9d7e552017-12-19 07:18:45 -05003345 iscoroutine_typecache = PySet_New(NULL);
3346 if (iscoroutine_typecache == NULL) {
3347 goto fail;
3348 }
3349
Yury Selivanovf23746a2018-01-22 19:11:18 -05003350
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003351 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003352 if (context_kwname == NULL) {
3353 goto fail;
3354 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003355
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003356#define WITH_MOD(NAME) \
3357 Py_CLEAR(module); \
3358 module = PyImport_ImportModule(NAME); \
3359 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003360 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003361 }
3362
3363#define GET_MOD_ATTR(VAR, NAME) \
3364 VAR = PyObject_GetAttrString(module, NAME); \
3365 if (VAR == NULL) { \
3366 goto fail; \
3367 }
3368
3369 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003370 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003371
3372 WITH_MOD("asyncio.base_futures")
3373 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003374
3375 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003376 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3377 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3378
3379 WITH_MOD("asyncio.base_tasks")
3380 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3381 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3382 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3383
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003384 WITH_MOD("asyncio.coroutines")
3385 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3386
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003387 WITH_MOD("traceback")
3388 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3389
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003390 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003391 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003392 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003393 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003394 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003395 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003396 goto fail;
3397 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003398
Serhiy Storchakabca49392017-09-03 08:10:14 +03003399 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003400 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003401
INADA Naokic411a7d2016-10-18 11:48:14 +09003402fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003403 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003404 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003405 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003406
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003407#undef WITH_MOD
3408#undef GET_MOD_ATTR
3409}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003410
INADA Naokic411a7d2016-10-18 11:48:14 +09003411PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003412
Yury Selivanova70232f2017-12-13 14:49:42 -05003413static PyMethodDef asyncio_methods[] = {
3414 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3415 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3416 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3417 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003418 _ASYNCIO__REGISTER_TASK_METHODDEF
3419 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3420 _ASYNCIO__ENTER_TASK_METHODDEF
3421 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003422 {NULL, NULL}
3423};
3424
INADA Naoki9f2ce252016-10-15 15:39:19 +09003425static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003426 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003427 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003428 module_doc, /* m_doc */
3429 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003430 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003431 NULL, /* m_slots */
3432 NULL, /* m_traverse */
3433 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003434 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003435};
3436
3437
3438PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003439PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003440{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003441 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003442 return NULL;
3443 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003444 if (PyType_Ready(&FutureIterType) < 0) {
3445 return NULL;
3446 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003447 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003448 return NULL;
3449 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003450 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003451 return NULL;
3452 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003453 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3454 return NULL;
3455 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003456
INADA Naoki9f2ce252016-10-15 15:39:19 +09003457 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003458 if (m == NULL) {
3459 return NULL;
3460 }
3461
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003462 /* FutureType and TaskType are made ready by PyModule_AddType() calls below. */
3463 if (PyModule_AddType(m, &FutureType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003464 Py_DECREF(m);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003465 return NULL;
3466 }
3467
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003468 if (PyModule_AddType(m, &TaskType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003469 Py_DECREF(m);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003470 return NULL;
3471 }
3472
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003473 Py_INCREF(all_tasks);
3474 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3475 Py_DECREF(all_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003476 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003477 return NULL;
3478 }
3479
3480 Py_INCREF(current_tasks);
3481 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3482 Py_DECREF(current_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003483 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003484 return NULL;
3485 }
3486
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003487 return m;
3488}