blob: 4d503a418a2e648594349874fd9055f57a814bac [file] [log] [blame]
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001#include "Python.h"
2#include "structmember.h"
3
4
Yury Selivanova0c1ba62016-10-28 12:52:37 -04005/*[clinic input]
6module _asyncio
7[clinic start generated code]*/
8/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
9
10
INADA Naoki9e4e38e2016-10-09 14:44:47 +090011/* identifiers used from some functions */
Yury Selivanova70232f2017-12-13 14:49:42 -050012_Py_IDENTIFIER(__asyncio_running_event_loop__);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +030013_Py_IDENTIFIER(_asyncio_future_blocking);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040014_Py_IDENTIFIER(add_done_callback);
Yury Selivanov416c1eb2018-05-28 17:54:02 -040015_Py_IDENTIFIER(_all_tasks_compat);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090016_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040017_Py_IDENTIFIER(cancel);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020018_Py_IDENTIFIER(current_task);
Yury Selivanova70232f2017-12-13 14:49:42 -050019_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040020_Py_IDENTIFIER(send);
21_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090022
23
INADA Naoki9f2ce252016-10-15 15:39:19 +090024/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020025static PyObject *asyncio_mod;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020026static PyObject *traceback_extract_stack;
27static PyObject *asyncio_get_event_loop_policy;
28static PyObject *asyncio_future_repr_info_func;
29static PyObject *asyncio_iscoroutine_func;
30static PyObject *asyncio_task_get_stack_func;
31static PyObject *asyncio_task_print_stack_func;
32static PyObject *asyncio_task_repr_info_func;
33static PyObject *asyncio_InvalidStateError;
34static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050035static PyObject *context_kwname;
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; \
69 fut_state prefix##_state; \
70 int prefix##_log_tb; \
71 int prefix##_blocking; \
72 PyObject *dict; \
73 PyObject *prefix##_weakreflist;
74
75typedef struct {
76 FutureObj_HEAD(fut)
77} FutureObj;
78
79typedef struct {
80 FutureObj_HEAD(task)
81 PyObject *task_fut_waiter;
82 PyObject *task_coro;
Alex Grönholmcca4eec2018-08-09 00:06:47 +030083 PyObject *task_name;
Yury Selivanov994269c2018-09-27 14:55:55 -040084 PyObject *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040085 int task_must_cancel;
86 int task_log_destroy_pending;
87} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090088
89typedef struct {
90 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040091 TaskObj *sw_task;
92 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030093} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090094
Yury Selivanova0c1ba62016-10-28 12:52:37 -040095typedef struct {
96 PyObject_HEAD
97 TaskObj *ww_task;
98} TaskWakeupMethWrapper;
99
Yury Selivanov9d411c12018-01-23 15:10:03 -0500100typedef struct {
101 PyObject_HEAD
102 PyObject *rl_loop;
103#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
104 pid_t rl_pid;
105#endif
106} PyRunningLoopHolder;
107
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400108
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500109static PyTypeObject FutureType;
110static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500111static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500112
113
114#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
115#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
116
117#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
118#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
119
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400120#include "clinic/_asynciomodule.c.h"
121
122
123/*[clinic input]
124class _asyncio.Future "FutureObj *" "&Future_Type"
125[clinic start generated code]*/
126/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
127
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500128
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400129/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500130static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900131
Yury Selivanov9d411c12018-01-23 15:10:03 -0500132static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
133
Yury Selivanova70232f2017-12-13 14:49:42 -0500134
135static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500136_is_coroutine(PyObject *coro)
137{
138 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
139 to check if it's another coroutine flavour.
140
141 Do this check after 'future_init()'; in case we need to raise
142 an error, __del__ needs a properly initialized object.
143 */
Jeroen Demeyer196a5302019-07-04 12:31:34 +0200144 PyObject *res = _PyObject_CallOneArg(asyncio_iscoroutine_func, coro);
Yury Selivanova9d7e552017-12-19 07:18:45 -0500145 if (res == NULL) {
146 return -1;
147 }
148
149 int is_res_true = PyObject_IsTrue(res);
150 Py_DECREF(res);
151 if (is_res_true <= 0) {
152 return is_res_true;
153 }
154
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200155 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500156 /* Just in case we don't want to cache more than 100
157 positive types. That shouldn't ever happen, unless
158 someone stressing the system on purpose.
159 */
160 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
161 return -1;
162 }
163 }
164
165 return 1;
166}
167
168
169static inline int
170is_coroutine(PyObject *coro)
171{
172 if (PyCoro_CheckExact(coro)) {
173 return 1;
174 }
175
176 /* Check if `type(coro)` is in the cache.
177 Caching makes is_coroutine() function almost as fast as
178 PyCoro_CheckExact() for non-native coroutine-like objects
179 (like coroutines compiled with Cython).
180
181 asyncio.iscoroutine() has its own type caching mechanism.
182 This cache allows us to avoid the cost of even calling
183 a pure-Python function in 99.9% cases.
184 */
185 int has_it = PySet_Contains(
186 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
187 if (has_it == 0) {
188 /* type(coro) is not in iscoroutine_typecache */
189 return _is_coroutine(coro);
190 }
191
Leo Ariasc3d95082018-02-03 18:36:10 -0600192 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500193 type(coro) is in iscoroutine_typecache
194 */
195 return has_it;
196}
197
198
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500199static PyObject *
200get_future_loop(PyObject *fut)
201{
202 /* Implementation of `asyncio.futures._get_loop` */
203
204 _Py_IDENTIFIER(get_loop);
205 _Py_IDENTIFIER(_loop);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300206 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500207
208 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
209 PyObject *loop = ((FutureObj *)fut)->fut_loop;
210 Py_INCREF(loop);
211 return loop;
212 }
213
Serhiy Storchaka66553542018-05-20 16:30:31 +0300214 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
215 return NULL;
216 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500217 if (getloop != NULL) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200218 PyObject *res = PyObject_CallNoArgs(getloop);
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500219 Py_DECREF(getloop);
220 return res;
221 }
222
223 return _PyObject_GetAttrId(fut, &PyId__loop);
224}
225
226
Yury Selivanova9d7e552017-12-19 07:18:45 -0500227static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500228get_running_loop(PyObject **loop)
229{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500230 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500231
Yury Selivanov9d411c12018-01-23 15:10:03 -0500232 PyThreadState *ts = PyThreadState_Get();
233 if (ts->id == cached_running_holder_tsid && cached_running_holder != NULL) {
234 // Fast path, check the cache.
235 rl = cached_running_holder; // borrowed
236 }
237 else {
238 if (ts->dict == NULL) {
239 goto not_found;
240 }
241
242 rl = _PyDict_GetItemIdWithError(
243 ts->dict, &PyId___asyncio_running_event_loop__); // borrowed
244 if (rl == NULL) {
245 if (PyErr_Occurred()) {
246 goto error;
247 }
248 else {
249 goto not_found;
250 }
251 }
252
253 cached_running_holder = rl; // borrowed
254 cached_running_holder_tsid = ts->id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500255 }
256
Yury Selivanov9d411c12018-01-23 15:10:03 -0500257 assert(Py_TYPE(rl) == &PyRunningLoopHolder_Type);
258 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500259
260 if (running_loop == Py_None) {
261 goto not_found;
262 }
263
Yury Selivanov9d411c12018-01-23 15:10:03 -0500264#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
265 /* On Windows there is no getpid, but there is also no os.fork(),
266 so there is no need for this check.
267 */
268 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
269 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500270 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500271#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500272
Yury Selivanov9d411c12018-01-23 15:10:03 -0500273 Py_INCREF(running_loop);
274 *loop = running_loop;
275 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500276
277not_found:
278 *loop = NULL;
279 return 0;
280
Yury Selivanova70232f2017-12-13 14:49:42 -0500281error:
282 *loop = NULL;
283 return -1;
284}
285
286
287static int
288set_running_loop(PyObject *loop)
289{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500290 cached_running_holder = NULL;
291 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500292
Yury Selivanov9d411c12018-01-23 15:10:03 -0500293 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500294 if (ts_dict == NULL) {
295 PyErr_SetString(
296 PyExc_RuntimeError, "thread-local storage is not available");
297 return -1;
298 }
299
Yury Selivanov9d411c12018-01-23 15:10:03 -0500300 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
301 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500302 return -1;
303 }
304
Yury Selivanova70232f2017-12-13 14:49:42 -0500305 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500306 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
307 {
308 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500309 return -1;
310 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500311 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500312
313 return 0;
314}
315
316
317static PyObject *
318get_event_loop(void)
319{
320 PyObject *loop;
321 PyObject *policy;
322
323 if (get_running_loop(&loop)) {
324 return NULL;
325 }
326 if (loop != NULL) {
327 return loop;
328 }
329
Victor Stinner2ff58a22019-06-17 14:27:23 +0200330 policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy);
Yury Selivanova70232f2017-12-13 14:49:42 -0500331 if (policy == NULL) {
332 return NULL;
333 }
334
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200335 loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
Yury Selivanova70232f2017-12-13 14:49:42 -0500336 Py_DECREF(policy);
337 return loop;
338}
339
340
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900341static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400342call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500343{
344 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500345 PyObject *stack[3];
346 Py_ssize_t nargs;
347
348 if (ctx == NULL) {
349 handle = _PyObject_CallMethodIdObjArgs(
350 loop, &PyId_call_soon, func, arg, NULL);
351 }
352 else {
353 /* Use FASTCALL to pass a keyword-only argument to call_soon */
354
355 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
356 if (callable == NULL) {
357 return -1;
358 }
359
360 /* All refs in 'stack' are borrowed. */
361 nargs = 1;
362 stack[0] = func;
363 if (arg != NULL) {
364 stack[1] = arg;
365 nargs++;
366 }
367 stack[nargs] = (PyObject *)ctx;
368
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200369 handle = _PyObject_Vectorcall(callable, stack, nargs, context_kwname);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500370 Py_DECREF(callable);
371 }
372
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500373 if (handle == NULL) {
374 return -1;
375 }
376 Py_DECREF(handle);
377 return 0;
378}
379
380
381static inline int
382future_is_alive(FutureObj *fut)
383{
384 return fut->fut_loop != NULL;
385}
386
387
388static inline int
389future_ensure_alive(FutureObj *fut)
390{
391 if (!future_is_alive(fut)) {
392 PyErr_SetString(PyExc_RuntimeError,
393 "Future object is not initialized.");
394 return -1;
395 }
396 return 0;
397}
398
399
400#define ENSURE_FUTURE_ALIVE(fut) \
401 do { \
402 assert(Future_Check(fut) || Task_Check(fut)); \
403 if (future_ensure_alive((FutureObj*)fut)) { \
404 return NULL; \
405 } \
406 } while(0);
407
408
409static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400410future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900411{
412 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500413 Py_ssize_t i;
414
415 if (fut->fut_callback0 != NULL) {
416 /* There's a 1st callback */
417
418 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500419 fut->fut_loop, fut->fut_callback0,
420 (PyObject *)fut, fut->fut_context0);
421
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500422 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500423 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500424 if (ret) {
425 /* If an error occurs in pure-Python implementation,
426 all callbacks are cleared. */
427 Py_CLEAR(fut->fut_callbacks);
428 return ret;
429 }
430
431 /* we called the first callback, now try calling
432 callbacks from the 'fut_callbacks' list. */
433 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900434
435 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500436 /* No more callbacks, return. */
437 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900438 }
439
440 len = PyList_GET_SIZE(fut->fut_callbacks);
441 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500442 /* The list of callbacks was empty; clear it and return. */
443 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900444 return 0;
445 }
446
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900447 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500448 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
449 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
450 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900451
Yury Selivanov994269c2018-09-27 14:55:55 -0400452 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500453 /* If an error occurs in pure-Python implementation,
454 all callbacks are cleared. */
455 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900456 return -1;
457 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900458 }
459
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500460 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900461 return 0;
462}
463
Oren Milmand019bc82018-02-13 12:28:33 +0200464
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900465static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400466future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900467{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300468 PyObject *res;
469 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900470 _Py_IDENTIFIER(get_debug);
471
Oren Milmand019bc82018-02-13 12:28:33 +0200472 // Same to FutureObj_clear() but not clearing fut->dict
473 Py_CLEAR(fut->fut_loop);
474 Py_CLEAR(fut->fut_callback0);
475 Py_CLEAR(fut->fut_context0);
476 Py_CLEAR(fut->fut_callbacks);
477 Py_CLEAR(fut->fut_result);
478 Py_CLEAR(fut->fut_exception);
479 Py_CLEAR(fut->fut_source_tb);
480
481 fut->fut_state = STATE_PENDING;
482 fut->fut_log_tb = 0;
483 fut->fut_blocking = 0;
484
Serhiy Storchakabca49392017-09-03 08:10:14 +0300485 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500486 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900487 if (loop == NULL) {
488 return -1;
489 }
490 }
491 else {
492 Py_INCREF(loop);
493 }
Oren Milmand019bc82018-02-13 12:28:33 +0200494 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900495
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200496 res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900497 if (res == NULL) {
498 return -1;
499 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300500 is_true = PyObject_IsTrue(res);
501 Py_DECREF(res);
502 if (is_true < 0) {
503 return -1;
504 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400505 if (is_true && !_Py_IsFinalizing()) {
506 /* Only try to capture the traceback if the interpreter is not being
507 finalized. The original motivation to add a `_Py_IsFinalizing()`
508 call was to prevent SIGSEGV when a Future is created in a __del__
509 method, which is called during the interpreter shutdown and the
510 traceback module is already unloaded.
511 */
Victor Stinner2ff58a22019-06-17 14:27:23 +0200512 fut->fut_source_tb = PyObject_CallNoArgs(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900513 if (fut->fut_source_tb == NULL) {
514 return -1;
515 }
516 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900517
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900518 return 0;
519}
520
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900521static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400522future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900523{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500524 if (future_ensure_alive(fut)) {
525 return NULL;
526 }
527
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900528 if (fut->fut_state != STATE_PENDING) {
529 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
530 return NULL;
531 }
532
Serhiy Storchakabca49392017-09-03 08:10:14 +0300533 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900534 Py_INCREF(res);
535 fut->fut_result = res;
536 fut->fut_state = STATE_FINISHED;
537
Yury Selivanov22feeb82018-01-24 11:31:01 -0500538 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900539 return NULL;
540 }
541 Py_RETURN_NONE;
542}
543
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900544static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400545future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900546{
547 PyObject *exc_val = NULL;
548
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900549 if (fut->fut_state != STATE_PENDING) {
550 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
551 return NULL;
552 }
553
554 if (PyExceptionClass_Check(exc)) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200555 exc_val = PyObject_CallNoArgs(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900556 if (exc_val == NULL) {
557 return NULL;
558 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300559 if (fut->fut_state != STATE_PENDING) {
560 Py_DECREF(exc_val);
561 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
562 return NULL;
563 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900564 }
565 else {
566 exc_val = exc;
567 Py_INCREF(exc_val);
568 }
569 if (!PyExceptionInstance_Check(exc_val)) {
570 Py_DECREF(exc_val);
571 PyErr_SetString(PyExc_TypeError, "invalid exception object");
572 return NULL;
573 }
574 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
575 Py_DECREF(exc_val);
576 PyErr_SetString(PyExc_TypeError,
577 "StopIteration interacts badly with generators "
578 "and cannot be raised into a Future");
579 return NULL;
580 }
581
Serhiy Storchakabca49392017-09-03 08:10:14 +0300582 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900583 fut->fut_exception = exc_val;
584 fut->fut_state = STATE_FINISHED;
585
Yury Selivanov22feeb82018-01-24 11:31:01 -0500586 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900587 return NULL;
588 }
589
590 fut->fut_log_tb = 1;
591 Py_RETURN_NONE;
592}
593
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400594static int
595future_get_result(FutureObj *fut, PyObject **result)
596{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400597 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300598 PyErr_SetNone(asyncio_CancelledError);
599 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400600 }
601
602 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300603 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
604 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400605 }
606
607 fut->fut_log_tb = 0;
608 if (fut->fut_exception != NULL) {
609 Py_INCREF(fut->fut_exception);
610 *result = fut->fut_exception;
611 return 1;
612 }
613
614 Py_INCREF(fut->fut_result);
615 *result = fut->fut_result;
616 return 0;
617}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900618
619static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400620future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900621{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500622 if (!future_is_alive(fut)) {
623 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
624 return NULL;
625 }
626
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900627 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500628 /* The future is done/cancelled, so schedule the callback
629 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500630 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900631 return NULL;
632 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900633 }
634 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500635 /* The future is pending, add a callback.
636
637 Callbacks in the future object are stored as follows:
638
639 callback0 -- a pointer to the first callback
640 callbacks -- a list of 2nd, 3rd, ... callbacks
641
642 Invariants:
643
644 * callbacks != NULL:
645 There are some callbacks in in the list. Just
646 add the new callback to it.
647
648 * callbacks == NULL and callback0 == NULL:
649 This is the first callback. Set it to callback0.
650
651 * callbacks == NULL and callback0 != NULL:
652 This is a second callback. Initialize callbacks
653 with a new list and add the new callback to it.
654 */
655
Yury Selivanovf23746a2018-01-22 19:11:18 -0500656 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500657 Py_INCREF(arg);
658 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500659 Py_INCREF(ctx);
660 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500661 }
662 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500663 PyObject *tup = PyTuple_New(2);
664 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500665 return NULL;
666 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500667 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500668 PyTuple_SET_ITEM(tup, 0, arg);
669 Py_INCREF(ctx);
670 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
671
672 if (fut->fut_callbacks != NULL) {
673 int err = PyList_Append(fut->fut_callbacks, tup);
674 if (err) {
675 Py_DECREF(tup);
676 return NULL;
677 }
678 Py_DECREF(tup);
679 }
680 else {
681 fut->fut_callbacks = PyList_New(1);
682 if (fut->fut_callbacks == NULL) {
683 return NULL;
684 }
685
686 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
687 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900688 }
689 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500690
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900691 Py_RETURN_NONE;
692}
693
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400694static PyObject *
695future_cancel(FutureObj *fut)
696{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000697 fut->fut_log_tb = 0;
698
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400699 if (fut->fut_state != STATE_PENDING) {
700 Py_RETURN_FALSE;
701 }
702 fut->fut_state = STATE_CANCELLED;
703
Yury Selivanov22feeb82018-01-24 11:31:01 -0500704 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400705 return NULL;
706 }
707
708 Py_RETURN_TRUE;
709}
710
711/*[clinic input]
712_asyncio.Future.__init__
713
714 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300715 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400716
717This class is *almost* compatible with concurrent.futures.Future.
718
719 Differences:
720
721 - result() and exception() do not take a timeout argument and
722 raise an exception when the future isn't done yet.
723
724 - Callbacks registered with add_done_callback() are always called
725 via the event loop's call_soon_threadsafe().
726
727 - This class is not compatible with the wait() and as_completed()
728 methods in the concurrent.futures package.
729[clinic start generated code]*/
730
731static int
732_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300733/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400734
735{
736 return future_init(self, loop);
737}
738
739static int
740FutureObj_clear(FutureObj *fut)
741{
742 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500743 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500744 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400745 Py_CLEAR(fut->fut_callbacks);
746 Py_CLEAR(fut->fut_result);
747 Py_CLEAR(fut->fut_exception);
748 Py_CLEAR(fut->fut_source_tb);
749 Py_CLEAR(fut->dict);
750 return 0;
751}
752
753static int
754FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
755{
756 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500757 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500758 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400759 Py_VISIT(fut->fut_callbacks);
760 Py_VISIT(fut->fut_result);
761 Py_VISIT(fut->fut_exception);
762 Py_VISIT(fut->fut_source_tb);
763 Py_VISIT(fut->dict);
764 return 0;
765}
766
767/*[clinic input]
768_asyncio.Future.result
769
770Return the result this future represents.
771
772If the future has been cancelled, raises CancelledError. If the
773future's result isn't yet available, raises InvalidStateError. If
774the future is done and has an exception set, this exception is raised.
775[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900776
777static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400778_asyncio_Future_result_impl(FutureObj *self)
779/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
780{
781 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500782
783 if (!future_is_alive(self)) {
784 PyErr_SetString(asyncio_InvalidStateError,
785 "Future object is not initialized.");
786 return NULL;
787 }
788
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400789 int res = future_get_result(self, &result);
790
791 if (res == -1) {
792 return NULL;
793 }
794
795 if (res == 0) {
796 return result;
797 }
798
799 assert(res == 1);
800
801 PyErr_SetObject(PyExceptionInstance_Class(result), result);
802 Py_DECREF(result);
803 return NULL;
804}
805
806/*[clinic input]
807_asyncio.Future.exception
808
809Return the exception that was set on this future.
810
811The exception (or None if no exception was set) is returned only if
812the future is done. If the future has been cancelled, raises
813CancelledError. If the future isn't done yet, raises
814InvalidStateError.
815[clinic start generated code]*/
816
817static PyObject *
818_asyncio_Future_exception_impl(FutureObj *self)
819/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
820{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500821 if (!future_is_alive(self)) {
822 PyErr_SetString(asyncio_InvalidStateError,
823 "Future object is not initialized.");
824 return NULL;
825 }
826
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400827 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300828 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400829 return NULL;
830 }
831
832 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300833 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400834 return NULL;
835 }
836
837 if (self->fut_exception != NULL) {
838 self->fut_log_tb = 0;
839 Py_INCREF(self->fut_exception);
840 return self->fut_exception;
841 }
842
843 Py_RETURN_NONE;
844}
845
846/*[clinic input]
847_asyncio.Future.set_result
848
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500849 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400850 /
851
852Mark the future done and set its result.
853
854If the future is already done when this method is called, raises
855InvalidStateError.
856[clinic start generated code]*/
857
858static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500859_asyncio_Future_set_result(FutureObj *self, PyObject *result)
860/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400861{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500862 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500863 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400864}
865
866/*[clinic input]
867_asyncio.Future.set_exception
868
Serhiy Storchakabca49392017-09-03 08:10:14 +0300869 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400870 /
871
872Mark the future done and set an exception.
873
874If the future is already done when this method is called, raises
875InvalidStateError.
876[clinic start generated code]*/
877
878static PyObject *
879_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300880/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400881{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500882 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400883 return future_set_exception(self, exception);
884}
885
886/*[clinic input]
887_asyncio.Future.add_done_callback
888
Serhiy Storchakabca49392017-09-03 08:10:14 +0300889 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400890 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500891 *
892 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400893
894Add a callback to be run when the future becomes done.
895
896The callback is called with a single argument - the future object. If
897the future is already done when this is called, the callback is
898scheduled with call_soon.
899[clinic start generated code]*/
900
901static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500902_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
903 PyObject *context)
904/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400905{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500906 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400907 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500908 if (context == NULL) {
909 return NULL;
910 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400911 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500912 Py_DECREF(context);
913 return res;
914 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400915 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400916}
917
918/*[clinic input]
919_asyncio.Future.remove_done_callback
920
Serhiy Storchakabca49392017-09-03 08:10:14 +0300921 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400922 /
923
924Remove all instances of a callback from the "call when done" list.
925
926Returns the number of callbacks removed.
927[clinic start generated code]*/
928
929static PyObject *
930_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300931/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900932{
933 PyObject *newlist;
934 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500935 Py_ssize_t cleared_callback0 = 0;
936
937 ENSURE_FUTURE_ALIVE(self)
938
939 if (self->fut_callback0 != NULL) {
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300940 int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500941 if (cmp == -1) {
942 return NULL;
943 }
944 if (cmp == 1) {
945 /* callback0 == fn */
946 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500947 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500948 cleared_callback0 = 1;
949 }
950 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900951
Serhiy Storchakabca49392017-09-03 08:10:14 +0300952 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500953 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300954 }
955
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400956 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900957 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500958 Py_CLEAR(self->fut_callbacks);
959 return PyLong_FromSsize_t(cleared_callback0);
960 }
961
962 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500963 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500964 int cmp = PyObject_RichCompareBool(
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300965 PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500966 if (cmp == -1) {
967 return NULL;
968 }
969 if (cmp == 1) {
970 /* callbacks[0] == fn */
971 Py_CLEAR(self->fut_callbacks);
972 return PyLong_FromSsize_t(1 + cleared_callback0);
973 }
974 /* callbacks[0] != fn and len(callbacks) == 1 */
975 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900976 }
977
978 newlist = PyList_New(len);
979 if (newlist == NULL) {
980 return NULL;
981 }
982
Yury Selivanov84af9032017-03-02 23:46:56 -0500983 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900984 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400985 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300986 Py_INCREF(item);
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300987 ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900988 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400989 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400990 PyList_SET_ITEM(newlist, j, item);
991 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300992 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400993 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300994 ret = PyList_Append(newlist, item);
995 }
996 Py_DECREF(item);
997 if (ret < 0) {
998 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900999 }
1000 }
1001
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001002 if (j == 0) {
1003 Py_CLEAR(self->fut_callbacks);
1004 Py_DECREF(newlist);
1005 return PyLong_FromSsize_t(len + cleared_callback0);
1006 }
1007
Serhiy Storchakabca49392017-09-03 08:10:14 +03001008 if (j < len) {
1009 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001010 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001011 j = PyList_GET_SIZE(newlist);
1012 len = PyList_GET_SIZE(self->fut_callbacks);
1013 if (j != len) {
1014 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1015 goto fail;
1016 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001017 }
1018 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001019 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001020
1021fail:
1022 Py_DECREF(newlist);
1023 return NULL;
1024}
1025
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001026/*[clinic input]
1027_asyncio.Future.cancel
1028
1029Cancel the future and schedule callbacks.
1030
1031If the future is already done or cancelled, return False. Otherwise,
1032change the future's state to cancelled, schedule the callbacks and
1033return True.
1034[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001035
1036static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001037_asyncio_Future_cancel_impl(FutureObj *self)
1038/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001039{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001040 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001041 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001042}
1043
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001044/*[clinic input]
1045_asyncio.Future.cancelled
1046
1047Return True if the future was cancelled.
1048[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001049
1050static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001051_asyncio_Future_cancelled_impl(FutureObj *self)
1052/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001053{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001054 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001055 Py_RETURN_TRUE;
1056 }
1057 else {
1058 Py_RETURN_FALSE;
1059 }
1060}
1061
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001062/*[clinic input]
1063_asyncio.Future.done
1064
1065Return True if the future is done.
1066
1067Done means either that a result / exception are available, or that the
1068future was cancelled.
1069[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001070
1071static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001072_asyncio_Future_done_impl(FutureObj *self)
1073/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001074{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001075 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001076 Py_RETURN_FALSE;
1077 }
1078 else {
1079 Py_RETURN_TRUE;
1080 }
1081}
1082
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001083/*[clinic input]
1084_asyncio.Future.get_loop
1085
1086Return the event loop the Future is bound to.
1087[clinic start generated code]*/
1088
1089static PyObject *
1090_asyncio_Future_get_loop_impl(FutureObj *self)
1091/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1092{
1093 Py_INCREF(self->fut_loop);
1094 return self->fut_loop;
1095}
1096
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001097static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001098FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001099{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001100 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001101 Py_RETURN_TRUE;
1102 }
1103 else {
1104 Py_RETURN_FALSE;
1105 }
1106}
1107
1108static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001109FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001110{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001111 if (future_ensure_alive(fut)) {
1112 return -1;
1113 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001114 if (val == NULL) {
1115 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1116 return -1;
1117 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001118
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001119 int is_true = PyObject_IsTrue(val);
1120 if (is_true < 0) {
1121 return -1;
1122 }
1123 fut->fut_blocking = is_true;
1124 return 0;
1125}
1126
1127static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001128FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001129{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001130 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001131 if (fut->fut_log_tb) {
1132 Py_RETURN_TRUE;
1133 }
1134 else {
1135 Py_RETURN_FALSE;
1136 }
1137}
1138
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001139static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001140FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001141{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001142 if (val == NULL) {
1143 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1144 return -1;
1145 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001146 int is_true = PyObject_IsTrue(val);
1147 if (is_true < 0) {
1148 return -1;
1149 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001150 if (is_true) {
1151 PyErr_SetString(PyExc_ValueError,
1152 "_log_traceback can only be set to False");
1153 return -1;
1154 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001155 fut->fut_log_tb = is_true;
1156 return 0;
1157}
1158
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001159static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001160FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001161{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001162 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001163 Py_RETURN_NONE;
1164 }
1165 Py_INCREF(fut->fut_loop);
1166 return fut->fut_loop;
1167}
1168
1169static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001170FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001171{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001172 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001173
1174 ENSURE_FUTURE_ALIVE(fut)
1175
Yury Selivanovf23746a2018-01-22 19:11:18 -05001176 if (fut->fut_callback0 == NULL) {
1177 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001178 Py_RETURN_NONE;
1179 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001180
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001181 Py_INCREF(fut->fut_callbacks);
1182 return fut->fut_callbacks;
1183 }
1184
Yury Selivanovf23746a2018-01-22 19:11:18 -05001185 Py_ssize_t len = 1;
1186 if (fut->fut_callbacks != NULL) {
1187 len += PyList_GET_SIZE(fut->fut_callbacks);
1188 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001189
Yury Selivanovf23746a2018-01-22 19:11:18 -05001190
1191 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001192 if (new_list == NULL) {
1193 return NULL;
1194 }
1195
Yury Selivanovf23746a2018-01-22 19:11:18 -05001196 PyObject *tup0 = PyTuple_New(2);
1197 if (tup0 == NULL) {
1198 Py_DECREF(new_list);
1199 return NULL;
1200 }
1201
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001202 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001203 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1204 assert(fut->fut_context0 != NULL);
1205 Py_INCREF(fut->fut_context0);
1206 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1207
1208 PyList_SET_ITEM(new_list, 0, tup0);
1209
1210 if (fut->fut_callbacks != NULL) {
1211 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1212 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1213 Py_INCREF(cb);
1214 PyList_SET_ITEM(new_list, i + 1, cb);
1215 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001216 }
1217
1218 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001219}
1220
1221static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001222FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001223{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001224 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001225 if (fut->fut_result == NULL) {
1226 Py_RETURN_NONE;
1227 }
1228 Py_INCREF(fut->fut_result);
1229 return fut->fut_result;
1230}
1231
1232static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001233FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001234{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001235 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001236 if (fut->fut_exception == NULL) {
1237 Py_RETURN_NONE;
1238 }
1239 Py_INCREF(fut->fut_exception);
1240 return fut->fut_exception;
1241}
1242
1243static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001244FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001245{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001246 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001247 Py_RETURN_NONE;
1248 }
1249 Py_INCREF(fut->fut_source_tb);
1250 return fut->fut_source_tb;
1251}
1252
1253static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001254FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001255{
1256 _Py_IDENTIFIER(PENDING);
1257 _Py_IDENTIFIER(CANCELLED);
1258 _Py_IDENTIFIER(FINISHED);
1259 PyObject *ret = NULL;
1260
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001261 ENSURE_FUTURE_ALIVE(fut)
1262
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001263 switch (fut->fut_state) {
1264 case STATE_PENDING:
1265 ret = _PyUnicode_FromId(&PyId_PENDING);
1266 break;
1267 case STATE_CANCELLED:
1268 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1269 break;
1270 case STATE_FINISHED:
1271 ret = _PyUnicode_FromId(&PyId_FINISHED);
1272 break;
1273 default:
1274 assert (0);
1275 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001276 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001277 return ret;
1278}
1279
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001280/*[clinic input]
1281_asyncio.Future._repr_info
1282[clinic start generated code]*/
1283
1284static PyObject *
1285_asyncio_Future__repr_info_impl(FutureObj *self)
1286/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001287{
Jeroen Demeyer196a5302019-07-04 12:31:34 +02001288 return _PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001289}
1290
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001291static PyObject *
1292FutureObj_repr(FutureObj *fut)
1293{
1294 _Py_IDENTIFIER(_repr_info);
1295
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001296 ENSURE_FUTURE_ALIVE(fut)
1297
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001298 PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
1299 &PyId__repr_info);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001300 if (rinfo == NULL) {
1301 return NULL;
1302 }
1303
Serhiy Storchakabca49392017-09-03 08:10:14 +03001304 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001305 Py_DECREF(rinfo);
1306 if (rinfo_s == NULL) {
1307 return NULL;
1308 }
1309
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001310 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1311 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001312 Py_DECREF(rinfo_s);
1313 return rstr;
1314}
1315
1316static void
1317FutureObj_finalize(FutureObj *fut)
1318{
1319 _Py_IDENTIFIER(call_exception_handler);
1320 _Py_IDENTIFIER(message);
1321 _Py_IDENTIFIER(exception);
1322 _Py_IDENTIFIER(future);
1323 _Py_IDENTIFIER(source_traceback);
1324
Serhiy Storchakabca49392017-09-03 08:10:14 +03001325 PyObject *error_type, *error_value, *error_traceback;
1326 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001327 PyObject *message = NULL;
1328 PyObject *func;
1329
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001330 if (!fut->fut_log_tb) {
1331 return;
1332 }
1333 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001334 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001335
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001336 /* Save the current exception, if any. */
1337 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1338
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001339 context = PyDict_New();
1340 if (context == NULL) {
1341 goto finally;
1342 }
1343
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001344 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001345 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001346 if (message == NULL) {
1347 goto finally;
1348 }
1349
1350 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1351 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1352 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1353 goto finally;
1354 }
1355 if (fut->fut_source_tb != NULL) {
1356 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1357 fut->fut_source_tb) < 0) {
1358 goto finally;
1359 }
1360 }
1361
1362 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1363 if (func != NULL) {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02001364 PyObject *res = _PyObject_CallOneArg(func, context);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001365 if (res == NULL) {
1366 PyErr_WriteUnraisable(func);
1367 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001368 else {
1369 Py_DECREF(res);
1370 }
1371 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001372 }
1373
1374finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001375 Py_XDECREF(context);
1376 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001377
1378 /* Restore the saved exception. */
1379 PyErr_Restore(error_type, error_value, error_traceback);
1380}
1381
1382
1383static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001384 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001385 0, /* am_aiter */
1386 0 /* am_anext */
1387};
1388
1389static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001390 _ASYNCIO_FUTURE_RESULT_METHODDEF
1391 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1392 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1393 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1394 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1395 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1396 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1397 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1398 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001399 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001400 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001401 {NULL, NULL} /* Sentinel */
1402};
1403
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001404#define FUTURE_COMMON_GETSETLIST \
1405 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1406 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1407 (setter)FutureObj_set_blocking, NULL}, \
1408 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1409 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1410 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1411 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001412 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1413 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001414 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001415
1416static PyGetSetDef FutureType_getsetlist[] = {
1417 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001418 {NULL} /* Sentinel */
1419};
1420
1421static void FutureObj_dealloc(PyObject *self);
1422
1423static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001424 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001425 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001426 sizeof(FutureObj), /* tp_basicsize */
1427 .tp_dealloc = FutureObj_dealloc,
1428 .tp_as_async = &FutureType_as_async,
1429 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001430 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001431 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001432 .tp_traverse = (traverseproc)FutureObj_traverse,
1433 .tp_clear = (inquiry)FutureObj_clear,
1434 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001435 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001436 .tp_methods = FutureType_methods,
1437 .tp_getset = FutureType_getsetlist,
1438 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001439 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001440 .tp_new = PyType_GenericNew,
1441 .tp_finalize = (destructor)FutureObj_finalize,
1442};
1443
1444static void
1445FutureObj_dealloc(PyObject *self)
1446{
1447 FutureObj *fut = (FutureObj *)self;
1448
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001449 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001450 /* When fut is subclass of Future, finalizer is called from
1451 * subtype_dealloc.
1452 */
1453 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1454 // resurrected.
1455 return;
1456 }
1457 }
1458
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001459 PyObject_GC_UnTrack(self);
1460
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001461 if (fut->fut_weakreflist != NULL) {
1462 PyObject_ClearWeakRefs(self);
1463 }
1464
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001465 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001466 Py_TYPE(fut)->tp_free(fut);
1467}
1468
1469
1470/*********************** Future Iterator **************************/
1471
1472typedef struct {
1473 PyObject_HEAD
1474 FutureObj *future;
1475} futureiterobject;
1476
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001477
1478#define FI_FREELIST_MAXLEN 255
1479static futureiterobject *fi_freelist = NULL;
1480static Py_ssize_t fi_freelist_len = 0;
1481
1482
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001483static void
1484FutureIter_dealloc(futureiterobject *it)
1485{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001486 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001487 Py_CLEAR(it->future);
1488
1489 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1490 fi_freelist_len++;
1491 it->future = (FutureObj*) fi_freelist;
1492 fi_freelist = it;
1493 }
1494 else {
1495 PyObject_GC_Del(it);
1496 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001497}
1498
1499static PyObject *
1500FutureIter_iternext(futureiterobject *it)
1501{
1502 PyObject *res;
1503 FutureObj *fut = it->future;
1504
1505 if (fut == NULL) {
1506 return NULL;
1507 }
1508
1509 if (fut->fut_state == STATE_PENDING) {
1510 if (!fut->fut_blocking) {
1511 fut->fut_blocking = 1;
1512 Py_INCREF(fut);
1513 return (PyObject *)fut;
1514 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001515 PyErr_SetString(PyExc_RuntimeError,
1516 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001517 return NULL;
1518 }
1519
Serhiy Storchakabca49392017-09-03 08:10:14 +03001520 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001521 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001522 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001523 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001524 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001525 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001526 }
1527
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001528 Py_DECREF(fut);
1529 return NULL;
1530}
1531
1532static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001533FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001534{
INADA Naoki74c17532016-10-25 19:00:45 +09001535 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001536 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001537 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001538 return FutureIter_iternext(self);
1539}
1540
1541static PyObject *
1542FutureIter_throw(futureiterobject *self, PyObject *args)
1543{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001544 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001545 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1546 return NULL;
1547
1548 if (val == Py_None) {
1549 val = NULL;
1550 }
1551 if (tb == Py_None) {
1552 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001553 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1554 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1555 return NULL;
1556 }
1557
1558 Py_INCREF(type);
1559 Py_XINCREF(val);
1560 Py_XINCREF(tb);
1561
1562 if (PyExceptionClass_Check(type)) {
1563 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001564 /* No need to call PyException_SetTraceback since we'll be calling
1565 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001566 } else if (PyExceptionInstance_Check(type)) {
1567 if (val) {
1568 PyErr_SetString(PyExc_TypeError,
1569 "instance exception may not have a separate value");
1570 goto fail;
1571 }
1572 val = type;
1573 type = PyExceptionInstance_Class(type);
1574 Py_INCREF(type);
1575 if (tb == NULL)
1576 tb = PyException_GetTraceback(val);
1577 } else {
1578 PyErr_SetString(PyExc_TypeError,
1579 "exceptions must be classes deriving BaseException or "
1580 "instances of such a class");
1581 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001582 }
1583
1584 Py_CLEAR(self->future);
1585
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001586 PyErr_Restore(type, val, tb);
1587
Serhiy Storchakabca49392017-09-03 08:10:14 +03001588 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001589
1590 fail:
1591 Py_DECREF(type);
1592 Py_XDECREF(val);
1593 Py_XDECREF(tb);
1594 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001595}
1596
1597static PyObject *
1598FutureIter_close(futureiterobject *self, PyObject *arg)
1599{
1600 Py_CLEAR(self->future);
1601 Py_RETURN_NONE;
1602}
1603
1604static int
1605FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1606{
1607 Py_VISIT(it->future);
1608 return 0;
1609}
1610
1611static PyMethodDef FutureIter_methods[] = {
1612 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1613 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1614 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1615 {NULL, NULL} /* Sentinel */
1616};
1617
1618static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001619 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001620 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001621 .tp_basicsize = sizeof(futureiterobject),
1622 .tp_itemsize = 0,
1623 .tp_dealloc = (destructor)FutureIter_dealloc,
1624 .tp_getattro = PyObject_GenericGetAttr,
1625 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1626 .tp_traverse = (traverseproc)FutureIter_traverse,
1627 .tp_iter = PyObject_SelfIter,
1628 .tp_iternext = (iternextfunc)FutureIter_iternext,
1629 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001630};
1631
1632static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001633future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001634{
1635 futureiterobject *it;
1636
1637 if (!PyObject_TypeCheck(fut, &FutureType)) {
1638 PyErr_BadInternalCall();
1639 return NULL;
1640 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001641
1642 ENSURE_FUTURE_ALIVE(fut)
1643
1644 if (fi_freelist_len) {
1645 fi_freelist_len--;
1646 it = fi_freelist;
1647 fi_freelist = (futureiterobject*) it->future;
1648 it->future = NULL;
1649 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001650 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001651 else {
1652 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1653 if (it == NULL) {
1654 return NULL;
1655 }
1656 }
1657
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001658 Py_INCREF(fut);
1659 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001660 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001661 return (PyObject*)it;
1662}
1663
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001664
1665/*********************** Task **************************/
1666
1667
1668/*[clinic input]
1669class _asyncio.Task "TaskObj *" "&Task_Type"
1670[clinic start generated code]*/
1671/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1672
1673static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001674static PyObject * task_wakeup(TaskObj *, PyObject *);
1675static PyObject * task_step(TaskObj *, PyObject *);
1676
1677/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001678
INADA Naokic411a7d2016-10-18 11:48:14 +09001679static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001680TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001681{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001682 Py_CLEAR(o->sw_task);
1683 Py_CLEAR(o->sw_arg);
1684 return 0;
1685}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001686
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001687static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001688TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001689{
1690 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001691 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001692 Py_TYPE(o)->tp_free(o);
1693}
1694
1695static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001696TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001697 PyObject *args, PyObject *kwds)
1698{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001699 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1700 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1701 return NULL;
1702 }
1703 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1704 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1705 return NULL;
1706 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001707 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001708}
1709
1710static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001711TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001712 visitproc visit, void *arg)
1713{
1714 Py_VISIT(o->sw_task);
1715 Py_VISIT(o->sw_arg);
1716 return 0;
1717}
1718
1719static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001720TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001721{
1722 if (o->sw_task) {
1723 Py_INCREF(o->sw_task);
1724 return (PyObject*)o->sw_task;
1725 }
1726 Py_RETURN_NONE;
1727}
1728
Serhiy Storchakabca49392017-09-03 08:10:14 +03001729static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1730 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001731 {NULL} /* Sentinel */
1732};
1733
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001734static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001735 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001736 "TaskStepMethWrapper",
1737 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001738 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001739 .tp_getset = TaskStepMethWrapper_getsetlist,
1740 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1741 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001742 .tp_getattro = PyObject_GenericGetAttr,
1743 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001744 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1745 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001746};
1747
1748static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001749TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001750{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001751 TaskStepMethWrapper *o;
1752 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001753 if (o == NULL) {
1754 return NULL;
1755 }
1756
1757 Py_INCREF(task);
1758 o->sw_task = task;
1759
1760 Py_XINCREF(arg);
1761 o->sw_arg = arg;
1762
1763 PyObject_GC_Track(o);
1764 return (PyObject*) o;
1765}
1766
1767/* ----- Task._wakeup wrapper */
1768
1769static PyObject *
1770TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1771 PyObject *args, PyObject *kwds)
1772{
1773 PyObject *fut;
1774
Serhiy Storchakabca49392017-09-03 08:10:14 +03001775 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1776 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1777 return NULL;
1778 }
1779 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001780 return NULL;
1781 }
1782
Yury Selivanov22feeb82018-01-24 11:31:01 -05001783 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001784}
1785
1786static int
1787TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1788{
1789 Py_CLEAR(o->ww_task);
1790 return 0;
1791}
1792
1793static int
1794TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1795 visitproc visit, void *arg)
1796{
1797 Py_VISIT(o->ww_task);
1798 return 0;
1799}
1800
1801static void
1802TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1803{
1804 PyObject_GC_UnTrack(o);
1805 (void)TaskWakeupMethWrapper_clear(o);
1806 Py_TYPE(o)->tp_free(o);
1807}
1808
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001809static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001810 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001811 "TaskWakeupMethWrapper",
1812 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1813 .tp_itemsize = 0,
1814 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1815 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1816 .tp_getattro = PyObject_GenericGetAttr,
1817 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1818 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1819 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1820};
1821
1822static PyObject *
1823TaskWakeupMethWrapper_new(TaskObj *task)
1824{
1825 TaskWakeupMethWrapper *o;
1826 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1827 if (o == NULL) {
1828 return NULL;
1829 }
1830
1831 Py_INCREF(task);
1832 o->ww_task = task;
1833
1834 PyObject_GC_Track(o);
1835 return (PyObject*) o;
1836}
1837
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001838/* ----- Task introspection helpers */
1839
1840static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001841register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001842{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001843 _Py_IDENTIFIER(add);
1844
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001845 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1846 &PyId_add, task);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001847 if (res == NULL) {
1848 return -1;
1849 }
1850 Py_DECREF(res);
1851 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001852}
1853
1854
1855static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001856unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001857{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001858 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001859
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001860 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1861 &PyId_discard, task);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001862 if (res == NULL) {
1863 return -1;
1864 }
1865 Py_DECREF(res);
1866 return 0;
1867}
1868
1869
1870static int
1871enter_task(PyObject *loop, PyObject *task)
1872{
1873 PyObject *item;
1874 Py_hash_t hash;
1875 hash = PyObject_Hash(loop);
1876 if (hash == -1) {
1877 return -1;
1878 }
1879 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1880 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001881 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001882 PyErr_Format(
1883 PyExc_RuntimeError,
1884 "Cannot enter into task %R while another " \
1885 "task %R is being executed.",
1886 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001887 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001888 return -1;
1889 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001890 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001891 return -1;
1892 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001893 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001894}
1895
1896
1897static int
1898leave_task(PyObject *loop, PyObject *task)
1899/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1900{
1901 PyObject *item;
1902 Py_hash_t hash;
1903 hash = PyObject_Hash(loop);
1904 if (hash == -1) {
1905 return -1;
1906 }
1907 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1908 if (item != task) {
1909 if (item == NULL) {
1910 /* Not entered, replace with None */
1911 item = Py_None;
1912 }
1913 PyErr_Format(
1914 PyExc_RuntimeError,
1915 "Leaving task %R does not match the current task %R.",
1916 task, item, NULL);
1917 return -1;
1918 }
1919 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1920}
1921
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001922/* ----- Task */
1923
1924/*[clinic input]
1925_asyncio.Task.__init__
1926
Serhiy Storchakabca49392017-09-03 08:10:14 +03001927 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001928 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001929 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001930 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001931
1932A coroutine wrapped in a Future.
1933[clinic start generated code]*/
1934
1935static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001936_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
1937 PyObject *name)
1938/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001939{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001940 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001941 return -1;
1942 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001943
Yury Selivanova9d7e552017-12-19 07:18:45 -05001944 int is_coro = is_coroutine(coro);
1945 if (is_coro == -1) {
1946 return -1;
1947 }
1948 if (is_coro == 0) {
1949 self->task_log_destroy_pending = 0;
1950 PyErr_Format(PyExc_TypeError,
1951 "a coroutine was expected, got %R",
1952 coro, NULL);
1953 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001954 }
1955
Oren Milmand019bc82018-02-13 12:28:33 +02001956 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001957 if (self->task_context == NULL) {
1958 return -1;
1959 }
1960
Oren Milmand019bc82018-02-13 12:28:33 +02001961 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001962 self->task_must_cancel = 0;
1963 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001964 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001965 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001966
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001967 if (name == Py_None) {
1968 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03001969 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001970 name = PyObject_Str(name);
1971 } else {
1972 Py_INCREF(name);
1973 }
1974 Py_XSETREF(self->task_name, name);
1975 if (self->task_name == NULL) {
1976 return -1;
1977 }
1978
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001979 if (task_call_step_soon(self, NULL)) {
1980 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001981 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001982 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001983}
1984
1985static int
1986TaskObj_clear(TaskObj *task)
1987{
1988 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001989 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001990 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001991 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001992 Py_CLEAR(task->task_fut_waiter);
1993 return 0;
1994}
1995
1996static int
1997TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1998{
Yury Selivanovf23746a2018-01-22 19:11:18 -05001999 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002000 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002001 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002002 Py_VISIT(task->task_fut_waiter);
2003 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2004 return 0;
2005}
2006
2007static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002008TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002009{
2010 if (task->task_log_destroy_pending) {
2011 Py_RETURN_TRUE;
2012 }
2013 else {
2014 Py_RETURN_FALSE;
2015 }
2016}
2017
2018static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002019TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002020{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002021 if (val == NULL) {
2022 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2023 return -1;
2024 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002025 int is_true = PyObject_IsTrue(val);
2026 if (is_true < 0) {
2027 return -1;
2028 }
2029 task->task_log_destroy_pending = is_true;
2030 return 0;
2031}
2032
2033static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002034TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002035{
2036 if (task->task_must_cancel) {
2037 Py_RETURN_TRUE;
2038 }
2039 else {
2040 Py_RETURN_FALSE;
2041 }
2042}
2043
2044static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002045TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002046{
2047 if (task->task_coro) {
2048 Py_INCREF(task->task_coro);
2049 return task->task_coro;
2050 }
2051
2052 Py_RETURN_NONE;
2053}
2054
2055static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002056TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002057{
2058 if (task->task_fut_waiter) {
2059 Py_INCREF(task->task_fut_waiter);
2060 return task->task_fut_waiter;
2061 }
2062
2063 Py_RETURN_NONE;
2064}
2065
2066/*[clinic input]
2067@classmethod
2068_asyncio.Task.current_task
2069
Serhiy Storchakabca49392017-09-03 08:10:14 +03002070 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002071
2072Return the currently running task in an event loop or None.
2073
2074By default the current task for the current event loop is returned.
2075
2076None is returned when called not in the context of a Task.
2077[clinic start generated code]*/
2078
2079static PyObject *
2080_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002081/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002082{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002083 PyObject *ret;
2084 PyObject *current_task_func;
2085
Inada Naokic5c6cda2019-03-22 20:07:32 +09002086 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002087 "Task.current_task() is deprecated, " \
2088 "use asyncio.current_task() instead",
2089 1) < 0) {
2090 return NULL;
2091 }
2092
2093 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2094 if (current_task_func == NULL) {
2095 return NULL;
2096 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002097
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002098 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002099 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002100 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002101 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002102 return NULL;
2103 }
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002104 ret = _PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002105 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002106 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002107 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002108 }
2109 else {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002110 ret = _PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002111 Py_DECREF(current_task_func);
2112 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002113 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002114}
2115
2116/*[clinic input]
2117@classmethod
2118_asyncio.Task.all_tasks
2119
Serhiy Storchakabca49392017-09-03 08:10:14 +03002120 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002121
2122Return a set of all tasks for an event loop.
2123
2124By default all tasks for the current event loop are returned.
2125[clinic start generated code]*/
2126
2127static PyObject *
2128_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002129/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002130{
2131 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002132 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002133
Inada Naokic5c6cda2019-03-22 20:07:32 +09002134 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002135 "Task.all_tasks() is deprecated, " \
2136 "use asyncio.all_tasks() instead",
2137 1) < 0) {
2138 return NULL;
2139 }
2140
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002141 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002142 if (all_tasks_func == NULL) {
2143 return NULL;
2144 }
2145
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002146 res = _PyObject_CallOneArg(all_tasks_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002147 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002148 return res;
2149}
2150
2151/*[clinic input]
2152_asyncio.Task._repr_info
2153[clinic start generated code]*/
2154
2155static PyObject *
2156_asyncio_Task__repr_info_impl(TaskObj *self)
2157/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2158{
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002159 return _PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002160}
2161
2162/*[clinic input]
2163_asyncio.Task.cancel
2164
2165Request that this task cancel itself.
2166
2167This arranges for a CancelledError to be thrown into the
2168wrapped coroutine on the next cycle through the event loop.
2169The coroutine then has a chance to clean up or even deny
2170the request using try/except/finally.
2171
2172Unlike Future.cancel, this does not guarantee that the
2173task will be cancelled: the exception might be caught and
2174acted upon, delaying cancellation of the task or preventing
2175cancellation completely. The task may also return a value or
2176raise a different exception.
2177
2178Immediately after this method is called, Task.cancelled() will
2179not return True (unless the task was already cancelled). A
2180task will be marked as cancelled when the wrapped coroutine
2181terminates with a CancelledError exception (even if cancel()
2182was not called).
2183[clinic start generated code]*/
2184
2185static PyObject *
2186_asyncio_Task_cancel_impl(TaskObj *self)
2187/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2188{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002189 self->task_log_tb = 0;
2190
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002191 if (self->task_state != STATE_PENDING) {
2192 Py_RETURN_FALSE;
2193 }
2194
2195 if (self->task_fut_waiter) {
2196 PyObject *res;
2197 int is_true;
2198
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002199 res = _PyObject_CallMethodIdNoArgs(self->task_fut_waiter, &PyId_cancel);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002200 if (res == NULL) {
2201 return NULL;
2202 }
2203
2204 is_true = PyObject_IsTrue(res);
2205 Py_DECREF(res);
2206 if (is_true < 0) {
2207 return NULL;
2208 }
2209
2210 if (is_true) {
2211 Py_RETURN_TRUE;
2212 }
2213 }
2214
2215 self->task_must_cancel = 1;
2216 Py_RETURN_TRUE;
2217}
2218
2219/*[clinic input]
2220_asyncio.Task.get_stack
2221
2222 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002223 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002224
2225Return the list of stack frames for this task's coroutine.
2226
2227If the coroutine is not done, this returns the stack where it is
2228suspended. If the coroutine has completed successfully or was
2229cancelled, this returns an empty list. If the coroutine was
2230terminated by an exception, this returns the list of traceback
2231frames.
2232
2233The frames are always ordered from oldest to newest.
2234
2235The optional limit gives the maximum number of frames to
2236return; by default all available frames are returned. Its
2237meaning differs depending on whether a stack or a traceback is
2238returned: the newest frames of a stack are returned, but the
2239oldest frames of a traceback are returned. (This matches the
2240behavior of the traceback module.)
2241
2242For reasons beyond our control, only one stack frame is
2243returned for a suspended coroutine.
2244[clinic start generated code]*/
2245
2246static PyObject *
2247_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002248/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002249{
2250 return PyObject_CallFunctionObjArgs(
2251 asyncio_task_get_stack_func, self, limit, NULL);
2252}
2253
2254/*[clinic input]
2255_asyncio.Task.print_stack
2256
2257 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002258 limit: object = None
2259 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002260
2261Print the stack or traceback for this task's coroutine.
2262
2263This produces output similar to that of the traceback module,
2264for the frames retrieved by get_stack(). The limit argument
2265is passed to get_stack(). The file argument is an I/O stream
2266to which the output is written; by default output is written
2267to sys.stderr.
2268[clinic start generated code]*/
2269
2270static PyObject *
2271_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2272 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002273/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002274{
2275 return PyObject_CallFunctionObjArgs(
2276 asyncio_task_print_stack_func, self, limit, file, NULL);
2277}
2278
2279/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002280_asyncio.Task.set_result
2281
2282 result: object
2283 /
2284[clinic start generated code]*/
2285
2286static PyObject *
2287_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2288/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2289{
2290 PyErr_SetString(PyExc_RuntimeError,
2291 "Task does not support set_result operation");
2292 return NULL;
2293}
2294
2295/*[clinic input]
2296_asyncio.Task.set_exception
2297
2298 exception: object
2299 /
2300[clinic start generated code]*/
2301
2302static PyObject *
2303_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2304/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2305{
2306 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002307 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002308 return NULL;
2309}
2310
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002311/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002312_asyncio.Task.get_coro
2313[clinic start generated code]*/
2314
2315static PyObject *
2316_asyncio_Task_get_coro_impl(TaskObj *self)
2317/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2318{
2319 Py_INCREF(self->task_coro);
2320 return self->task_coro;
2321}
2322
2323/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002324_asyncio.Task.get_name
2325[clinic start generated code]*/
2326
2327static PyObject *
2328_asyncio_Task_get_name_impl(TaskObj *self)
2329/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2330{
2331 if (self->task_name) {
2332 Py_INCREF(self->task_name);
2333 return self->task_name;
2334 }
2335
2336 Py_RETURN_NONE;
2337}
2338
2339/*[clinic input]
2340_asyncio.Task.set_name
2341
2342 value: object
2343 /
2344[clinic start generated code]*/
2345
2346static PyObject *
2347_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2348/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2349{
Alex Grönholma7548232018-08-09 23:49:49 +03002350 if (!PyUnicode_CheckExact(value)) {
2351 value = PyObject_Str(value);
2352 if (value == NULL) {
2353 return NULL;
2354 }
2355 } else {
2356 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002357 }
2358
Alex Grönholma7548232018-08-09 23:49:49 +03002359 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002360 Py_RETURN_NONE;
2361}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002362
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002363static void
2364TaskObj_finalize(TaskObj *task)
2365{
2366 _Py_IDENTIFIER(call_exception_handler);
2367 _Py_IDENTIFIER(task);
2368 _Py_IDENTIFIER(message);
2369 _Py_IDENTIFIER(source_traceback);
2370
Serhiy Storchakabca49392017-09-03 08:10:14 +03002371 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002372 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002373 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002374 PyObject *error_type, *error_value, *error_traceback;
2375
2376 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2377 goto done;
2378 }
2379
2380 /* Save the current exception, if any. */
2381 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2382
2383 context = PyDict_New();
2384 if (context == NULL) {
2385 goto finally;
2386 }
2387
2388 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2389 if (message == NULL) {
2390 goto finally;
2391 }
2392
2393 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2394 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2395 {
2396 goto finally;
2397 }
2398
2399 if (task->task_source_tb != NULL) {
2400 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2401 task->task_source_tb) < 0)
2402 {
2403 goto finally;
2404 }
2405 }
2406
2407 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2408 if (func != NULL) {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002409 PyObject *res = _PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002410 if (res == NULL) {
2411 PyErr_WriteUnraisable(func);
2412 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002413 else {
2414 Py_DECREF(res);
2415 }
2416 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002417 }
2418
2419finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002420 Py_XDECREF(context);
2421 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002422
2423 /* Restore the saved exception. */
2424 PyErr_Restore(error_type, error_value, error_traceback);
2425
2426done:
2427 FutureObj_finalize((FutureObj*)task);
2428}
2429
2430static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2431
2432static PyMethodDef TaskType_methods[] = {
2433 _ASYNCIO_FUTURE_RESULT_METHODDEF
2434 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002435 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2436 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2437 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2438 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002439 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2440 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002441 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2442 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2443 _ASYNCIO_TASK_CANCEL_METHODDEF
2444 _ASYNCIO_TASK_GET_STACK_METHODDEF
2445 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002446 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002447 _ASYNCIO_TASK_GET_NAME_METHODDEF
2448 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002449 _ASYNCIO_TASK_GET_CORO_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002450 {NULL, NULL} /* Sentinel */
2451};
2452
2453static PyGetSetDef TaskType_getsetlist[] = {
2454 FUTURE_COMMON_GETSETLIST
2455 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2456 (setter)TaskObj_set_log_destroy_pending, NULL},
2457 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2458 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2459 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2460 {NULL} /* Sentinel */
2461};
2462
2463static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002464 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002465 "_asyncio.Task",
2466 sizeof(TaskObj), /* tp_basicsize */
2467 .tp_base = &FutureType,
2468 .tp_dealloc = TaskObj_dealloc,
2469 .tp_as_async = &FutureType_as_async,
2470 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002471 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002472 .tp_doc = _asyncio_Task___init____doc__,
2473 .tp_traverse = (traverseproc)TaskObj_traverse,
2474 .tp_clear = (inquiry)TaskObj_clear,
2475 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2476 .tp_iter = (getiterfunc)future_new_iter,
2477 .tp_methods = TaskType_methods,
2478 .tp_getset = TaskType_getsetlist,
2479 .tp_dictoffset = offsetof(TaskObj, dict),
2480 .tp_init = (initproc)_asyncio_Task___init__,
2481 .tp_new = PyType_GenericNew,
2482 .tp_finalize = (destructor)TaskObj_finalize,
2483};
2484
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002485static void
2486TaskObj_dealloc(PyObject *self)
2487{
2488 TaskObj *task = (TaskObj *)self;
2489
2490 if (Task_CheckExact(self)) {
2491 /* When fut is subclass of Task, finalizer is called from
2492 * subtype_dealloc.
2493 */
2494 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2495 // resurrected.
2496 return;
2497 }
2498 }
2499
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002500 PyObject_GC_UnTrack(self);
2501
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002502 if (task->task_weakreflist != NULL) {
2503 PyObject_ClearWeakRefs(self);
2504 }
2505
2506 (void)TaskObj_clear(task);
2507 Py_TYPE(task)->tp_free(task);
2508}
2509
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002510static int
2511task_call_step_soon(TaskObj *task, PyObject *arg)
2512{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002513 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002514 if (cb == NULL) {
2515 return -1;
2516 }
2517
Yury Selivanovf23746a2018-01-22 19:11:18 -05002518 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002519 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002520 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002521}
2522
2523static PyObject *
2524task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2525{
2526 PyObject* msg;
2527
2528 va_list vargs;
2529#ifdef HAVE_STDARG_PROTOTYPES
2530 va_start(vargs, format);
2531#else
2532 va_start(vargs);
2533#endif
2534 msg = PyUnicode_FromFormatV(format, vargs);
2535 va_end(vargs);
2536
2537 if (msg == NULL) {
2538 return NULL;
2539 }
2540
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002541 PyObject *e = _PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002542 Py_DECREF(msg);
2543 if (e == NULL) {
2544 return NULL;
2545 }
2546
2547 if (task_call_step_soon(task, e) == -1) {
2548 Py_DECREF(e);
2549 return NULL;
2550 }
2551
2552 Py_DECREF(e);
2553 Py_RETURN_NONE;
2554}
2555
2556static PyObject *
2557task_step_impl(TaskObj *task, PyObject *exc)
2558{
2559 int res;
2560 int clear_exc = 0;
2561 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002562 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002563 PyObject *o;
2564
2565 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002566 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002567 "_step(): already done: %R %R",
2568 task,
2569 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002570 goto fail;
2571 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002572
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002573 if (task->task_must_cancel) {
2574 assert(exc != Py_None);
2575
2576 if (exc) {
2577 /* Check if exc is a CancelledError */
2578 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2579 if (res == -1) {
2580 /* An error occurred, abort */
2581 goto fail;
2582 }
2583 if (res == 0) {
2584 /* exc is not CancelledError; reset it to NULL */
2585 exc = NULL;
2586 }
2587 }
2588
2589 if (!exc) {
2590 /* exc was not a CancelledError */
Victor Stinner2ff58a22019-06-17 14:27:23 +02002591 exc = PyObject_CallNoArgs(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002592 if (!exc) {
2593 goto fail;
2594 }
2595 clear_exc = 1;
2596 }
2597
2598 task->task_must_cancel = 0;
2599 }
2600
2601 Py_CLEAR(task->task_fut_waiter);
2602
Serhiy Storchakabca49392017-09-03 08:10:14 +03002603 coro = task->task_coro;
2604 if (coro == NULL) {
2605 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2606 return NULL;
2607 }
2608
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002609 if (exc == NULL) {
2610 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2611 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2612 }
2613 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002614 result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002615 }
2616 }
2617 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002618 result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002619 if (clear_exc) {
2620 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002621 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002622 }
2623 }
2624
2625 if (result == NULL) {
2626 PyObject *et, *ev, *tb;
2627
2628 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2629 /* The error is StopIteration and that means that
2630 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002631 if (task->task_must_cancel) {
2632 // Task is cancelled right before coro stops.
2633 Py_DECREF(o);
2634 task->task_must_cancel = 0;
2635 et = asyncio_CancelledError;
2636 Py_INCREF(et);
2637 ev = NULL;
2638 tb = NULL;
2639 goto set_exception;
2640 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002641 PyObject *res = future_set_result((FutureObj*)task, o);
2642 Py_DECREF(o);
2643 if (res == NULL) {
2644 return NULL;
2645 }
2646 Py_DECREF(res);
2647 Py_RETURN_NONE;
2648 }
2649
2650 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2651 /* CancelledError */
2652 PyErr_Clear();
2653 return future_cancel((FutureObj*)task);
2654 }
2655
2656 /* Some other exception; pop it and call Task.set_exception() */
2657 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002658
2659set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002660 assert(et);
2661 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2662 PyErr_NormalizeException(&et, &ev, &tb);
2663 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002664 if (tb != NULL) {
2665 PyException_SetTraceback(ev, tb);
2666 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002667 o = future_set_exception((FutureObj*)task, ev);
2668 if (!o) {
2669 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002670 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002671 Py_XDECREF(tb);
2672 Py_XDECREF(ev);
2673 goto fail;
2674 }
2675 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002676 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002677
Yury Selivanov431b5402019-05-27 14:45:12 +02002678 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2679 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2680 {
2681 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002682 PyErr_Restore(et, ev, tb);
2683 goto fail;
2684 }
2685
Serhiy Storchakabca49392017-09-03 08:10:14 +03002686 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002687 Py_XDECREF(tb);
2688 Py_XDECREF(ev);
2689
2690 Py_RETURN_NONE;
2691 }
2692
2693 if (result == (PyObject*)task) {
2694 /* We have a task that wants to await on itself */
2695 goto self_await;
2696 }
2697
2698 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2699 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2700 PyObject *wrapper;
2701 PyObject *res;
2702 FutureObj *fut = (FutureObj*)result;
2703
2704 /* Check if `result` future is attached to a different loop */
2705 if (fut->fut_loop != task->task_loop) {
2706 goto different_loop;
2707 }
2708
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002709 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002710 goto yield_insteadof_yf;
2711 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002712
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002713 fut->fut_blocking = 0;
2714
2715 /* result.add_done_callback(task._wakeup) */
2716 wrapper = TaskWakeupMethWrapper_new(task);
2717 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002718 goto fail;
2719 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002720 res = future_add_done_callback(
2721 (FutureObj*)result, wrapper, task->task_context);
2722 Py_DECREF(wrapper);
2723 if (res == NULL) {
2724 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002725 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002726 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002727
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002728 /* task._fut_waiter = result */
2729 task->task_fut_waiter = result; /* no incref is necessary */
2730
2731 if (task->task_must_cancel) {
2732 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002733 int is_true;
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002734 r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002735 if (r == NULL) {
2736 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002737 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002738 is_true = PyObject_IsTrue(r);
2739 Py_DECREF(r);
2740 if (is_true < 0) {
2741 return NULL;
2742 }
2743 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002744 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002745 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002746 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002747
2748 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002749 }
2750
2751 /* Check if `result` is None */
2752 if (result == Py_None) {
2753 /* Bare yield relinquishes control for one event loop iteration. */
2754 if (task_call_step_soon(task, NULL)) {
2755 goto fail;
2756 }
2757 return result;
2758 }
2759
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002760 /* Check if `result` is a Future-compatible object */
2761 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2762 goto fail;
2763 }
2764 if (o != NULL && o != Py_None) {
2765 /* `result` is a Future-compatible object */
2766 PyObject *wrapper;
2767 PyObject *res;
2768
2769 int blocking = PyObject_IsTrue(o);
2770 Py_DECREF(o);
2771 if (blocking < 0) {
2772 goto fail;
2773 }
2774
2775 /* Check if `result` future is attached to a different loop */
2776 PyObject *oloop = get_future_loop(result);
2777 if (oloop == NULL) {
2778 goto fail;
2779 }
2780 if (oloop != task->task_loop) {
2781 Py_DECREF(oloop);
2782 goto different_loop;
2783 }
2784 Py_DECREF(oloop);
2785
2786 if (!blocking) {
2787 goto yield_insteadof_yf;
2788 }
2789
2790 /* result._asyncio_future_blocking = False */
2791 if (_PyObject_SetAttrId(
2792 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2793 goto fail;
2794 }
2795
2796 wrapper = TaskWakeupMethWrapper_new(task);
2797 if (wrapper == NULL) {
2798 goto fail;
2799 }
2800
2801 /* result.add_done_callback(task._wakeup) */
2802 PyObject *add_cb = _PyObject_GetAttrId(
2803 result, &PyId_add_done_callback);
2804 if (add_cb == NULL) {
2805 Py_DECREF(wrapper);
2806 goto fail;
2807 }
2808 PyObject *stack[2];
2809 stack[0] = wrapper;
2810 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002811 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002812 Py_DECREF(add_cb);
2813 Py_DECREF(wrapper);
2814 if (res == NULL) {
2815 goto fail;
2816 }
2817 Py_DECREF(res);
2818
2819 /* task._fut_waiter = result */
2820 task->task_fut_waiter = result; /* no incref is necessary */
2821
2822 if (task->task_must_cancel) {
2823 PyObject *r;
2824 int is_true;
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002825 r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002826 if (r == NULL) {
2827 return NULL;
2828 }
2829 is_true = PyObject_IsTrue(r);
2830 Py_DECREF(r);
2831 if (is_true < 0) {
2832 return NULL;
2833 }
2834 else if (is_true) {
2835 task->task_must_cancel = 0;
2836 }
2837 }
2838
2839 Py_RETURN_NONE;
2840 }
2841
2842 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002843 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002844 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2845 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002846 goto fail;
2847 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002848 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002849 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002850 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002851 task, PyExc_RuntimeError,
2852 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002853 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002854 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002855 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002856 }
2857
2858 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002859 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002860 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002861 Py_DECREF(result);
2862 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002863
2864self_await:
2865 o = task_set_error_soon(
2866 task, PyExc_RuntimeError,
2867 "Task cannot await on itself: %R", task);
2868 Py_DECREF(result);
2869 return o;
2870
2871yield_insteadof_yf:
2872 o = task_set_error_soon(
2873 task, PyExc_RuntimeError,
2874 "yield was used instead of yield from "
2875 "in task %R with %R",
2876 task, result);
2877 Py_DECREF(result);
2878 return o;
2879
2880different_loop:
2881 o = task_set_error_soon(
2882 task, PyExc_RuntimeError,
2883 "Task %R got Future %R attached to a different loop",
2884 task, result);
2885 Py_DECREF(result);
2886 return o;
2887
2888fail:
2889 Py_XDECREF(result);
2890 return NULL;
2891}
2892
2893static PyObject *
2894task_step(TaskObj *task, PyObject *exc)
2895{
2896 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002897
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002898 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002899 return NULL;
2900 }
2901
2902 res = task_step_impl(task, exc);
2903
2904 if (res == NULL) {
2905 PyObject *et, *ev, *tb;
2906 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002907 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002908 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002909 return NULL;
2910 }
2911 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002912 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002913 Py_DECREF(res);
2914 return NULL;
2915 }
2916 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002917 return res;
2918 }
2919 }
2920}
2921
2922static PyObject *
2923task_wakeup(TaskObj *task, PyObject *o)
2924{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002925 PyObject *et, *ev, *tb;
2926 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002927 assert(o);
2928
2929 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2930 PyObject *fut_result = NULL;
2931 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002932
2933 switch(res) {
2934 case -1:
2935 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002936 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002937 case 0:
2938 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002939 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002940 default:
2941 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002942 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002943 Py_DECREF(fut_result);
2944 return result;
2945 }
2946 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002947 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002948 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2949 if (fut_result != NULL) {
2950 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002951 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002952 }
2953 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002954 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002955
2956 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002957 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2958 PyErr_NormalizeException(&et, &ev, &tb);
2959 }
2960
Yury Selivanov22feeb82018-01-24 11:31:01 -05002961 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002962
2963 Py_DECREF(et);
2964 Py_XDECREF(tb);
2965 Py_XDECREF(ev);
2966
2967 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002968}
2969
2970
Yury Selivanova70232f2017-12-13 14:49:42 -05002971/*********************** Functions **************************/
2972
2973
2974/*[clinic input]
2975_asyncio._get_running_loop
2976
2977Return the running event loop or None.
2978
2979This is a low-level function intended to be used by event loops.
2980This function is thread-specific.
2981
2982[clinic start generated code]*/
2983
2984static PyObject *
2985_asyncio__get_running_loop_impl(PyObject *module)
2986/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2987{
2988 PyObject *loop;
2989 if (get_running_loop(&loop)) {
2990 return NULL;
2991 }
2992 if (loop == NULL) {
2993 /* There's no currently running event loop */
2994 Py_RETURN_NONE;
2995 }
2996 return loop;
2997}
2998
2999/*[clinic input]
3000_asyncio._set_running_loop
3001 loop: 'O'
3002 /
3003
3004Set the running event loop.
3005
3006This is a low-level function intended to be used by event loops.
3007This function is thread-specific.
3008[clinic start generated code]*/
3009
3010static PyObject *
3011_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3012/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3013{
3014 if (set_running_loop(loop)) {
3015 return NULL;
3016 }
3017 Py_RETURN_NONE;
3018}
3019
3020/*[clinic input]
3021_asyncio.get_event_loop
3022
3023Return an asyncio event loop.
3024
3025When called from a coroutine or a callback (e.g. scheduled with
3026call_soon or similar API), this function will always return the
3027running event loop.
3028
3029If there is no running event loop set, the function will return
3030the result of `get_event_loop_policy().get_event_loop()` call.
3031[clinic start generated code]*/
3032
3033static PyObject *
3034_asyncio_get_event_loop_impl(PyObject *module)
3035/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3036{
3037 return get_event_loop();
3038}
3039
3040/*[clinic input]
3041_asyncio.get_running_loop
3042
3043Return the running event loop. Raise a RuntimeError if there is none.
3044
3045This function is thread-specific.
3046[clinic start generated code]*/
3047
3048static PyObject *
3049_asyncio_get_running_loop_impl(PyObject *module)
3050/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3051{
3052 PyObject *loop;
3053 if (get_running_loop(&loop)) {
3054 return NULL;
3055 }
3056 if (loop == NULL) {
3057 /* There's no currently running event loop */
3058 PyErr_SetString(
3059 PyExc_RuntimeError, "no running event loop");
3060 }
3061 return loop;
3062}
3063
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003064/*[clinic input]
3065_asyncio._register_task
3066
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003067 task: object
3068
3069Register a new task in asyncio as executed by loop.
3070
3071Returns None.
3072[clinic start generated code]*/
3073
3074static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003075_asyncio__register_task_impl(PyObject *module, PyObject *task)
3076/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003077{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003078 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003079 return NULL;
3080 }
3081 Py_RETURN_NONE;
3082}
3083
3084
3085/*[clinic input]
3086_asyncio._unregister_task
3087
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003088 task: object
3089
3090Unregister a task.
3091
3092Returns None.
3093[clinic start generated code]*/
3094
3095static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003096_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3097/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003098{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003099 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003100 return NULL;
3101 }
3102 Py_RETURN_NONE;
3103}
3104
3105
3106/*[clinic input]
3107_asyncio._enter_task
3108
3109 loop: object
3110 task: object
3111
3112Enter into task execution or resume suspended task.
3113
3114Task belongs to loop.
3115
3116Returns None.
3117[clinic start generated code]*/
3118
3119static PyObject *
3120_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3121/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3122{
3123 if (enter_task(loop, task) < 0) {
3124 return NULL;
3125 }
3126 Py_RETURN_NONE;
3127}
3128
3129
3130/*[clinic input]
3131_asyncio._leave_task
3132
3133 loop: object
3134 task: object
3135
3136Leave task execution or suspend a task.
3137
3138Task belongs to loop.
3139
3140Returns None.
3141[clinic start generated code]*/
3142
3143static PyObject *
3144_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3145/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3146{
3147 if (leave_task(loop, task) < 0) {
3148 return NULL;
3149 }
3150 Py_RETURN_NONE;
3151}
3152
Yury Selivanova70232f2017-12-13 14:49:42 -05003153
Yury Selivanov9d411c12018-01-23 15:10:03 -05003154/*********************** PyRunningLoopHolder ********************/
3155
3156
3157static PyRunningLoopHolder *
3158new_running_loop_holder(PyObject *loop)
3159{
3160 PyRunningLoopHolder *rl = PyObject_New(
3161 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3162 if (rl == NULL) {
3163 return NULL;
3164 }
3165
3166#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3167 rl->rl_pid = getpid();
3168#endif
3169
3170 Py_INCREF(loop);
3171 rl->rl_loop = loop;
3172
3173 return rl;
3174}
3175
3176
3177static void
3178PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3179{
3180 Py_CLEAR(rl->rl_loop);
3181 PyObject_Free(rl);
3182}
3183
3184
3185static PyTypeObject PyRunningLoopHolder_Type = {
3186 PyVarObject_HEAD_INIT(NULL, 0)
3187 "_RunningLoopHolder",
3188 sizeof(PyRunningLoopHolder),
3189 .tp_getattro = PyObject_GenericGetAttr,
3190 .tp_flags = Py_TPFLAGS_DEFAULT,
3191 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3192};
3193
3194
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003195/*********************** Module **************************/
3196
3197
3198static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003199module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003200{
3201 PyObject *next;
3202 PyObject *current;
3203
3204 next = (PyObject*) fi_freelist;
3205 while (next != NULL) {
3206 assert(fi_freelist_len > 0);
3207 fi_freelist_len--;
3208
3209 current = next;
3210 next = (PyObject*) ((futureiterobject*) current)->future;
3211 PyObject_GC_Del(current);
3212 }
3213 assert(fi_freelist_len == 0);
3214 fi_freelist = NULL;
3215}
3216
3217
3218static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003219module_free(void *m)
3220{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003221 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003222 Py_CLEAR(traceback_extract_stack);
3223 Py_CLEAR(asyncio_future_repr_info_func);
3224 Py_CLEAR(asyncio_get_event_loop_policy);
3225 Py_CLEAR(asyncio_iscoroutine_func);
3226 Py_CLEAR(asyncio_task_get_stack_func);
3227 Py_CLEAR(asyncio_task_print_stack_func);
3228 Py_CLEAR(asyncio_task_repr_info_func);
3229 Py_CLEAR(asyncio_InvalidStateError);
3230 Py_CLEAR(asyncio_CancelledError);
3231
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003232 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003233 Py_CLEAR(current_tasks);
3234 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003235
Yury Selivanovf23746a2018-01-22 19:11:18 -05003236 Py_CLEAR(context_kwname);
3237
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003238 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003239}
3240
3241static int
3242module_init(void)
3243{
3244 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003245
3246 asyncio_mod = PyImport_ImportModule("asyncio");
3247 if (asyncio_mod == NULL) {
3248 goto fail;
3249 }
3250
3251 current_tasks = PyDict_New();
3252 if (current_tasks == NULL) {
3253 goto fail;
3254 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003255
Yury Selivanova9d7e552017-12-19 07:18:45 -05003256 iscoroutine_typecache = PySet_New(NULL);
3257 if (iscoroutine_typecache == NULL) {
3258 goto fail;
3259 }
3260
Yury Selivanovf23746a2018-01-22 19:11:18 -05003261
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003262 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003263 if (context_kwname == NULL) {
3264 goto fail;
3265 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003266
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003267#define WITH_MOD(NAME) \
3268 Py_CLEAR(module); \
3269 module = PyImport_ImportModule(NAME); \
3270 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003271 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003272 }
3273
3274#define GET_MOD_ATTR(VAR, NAME) \
3275 VAR = PyObject_GetAttrString(module, NAME); \
3276 if (VAR == NULL) { \
3277 goto fail; \
3278 }
3279
3280 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003281 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003282
3283 WITH_MOD("asyncio.base_futures")
3284 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003285
3286 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003287 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3288 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3289
3290 WITH_MOD("asyncio.base_tasks")
3291 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3292 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3293 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3294
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003295 WITH_MOD("asyncio.coroutines")
3296 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3297
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003298 WITH_MOD("traceback")
3299 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3300
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003301 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003302 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003303 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003304 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003305 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003306 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003307 goto fail;
3308 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003309
Serhiy Storchakabca49392017-09-03 08:10:14 +03003310 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003311 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003312
INADA Naokic411a7d2016-10-18 11:48:14 +09003313fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003314 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003315 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003316 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003317
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003318#undef WITH_MOD
3319#undef GET_MOD_ATTR
3320}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003321
INADA Naokic411a7d2016-10-18 11:48:14 +09003322PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003323
Yury Selivanova70232f2017-12-13 14:49:42 -05003324static PyMethodDef asyncio_methods[] = {
3325 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3326 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3327 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3328 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003329 _ASYNCIO__REGISTER_TASK_METHODDEF
3330 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3331 _ASYNCIO__ENTER_TASK_METHODDEF
3332 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003333 {NULL, NULL}
3334};
3335
INADA Naoki9f2ce252016-10-15 15:39:19 +09003336static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003337 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003338 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003339 module_doc, /* m_doc */
3340 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003341 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003342 NULL, /* m_slots */
3343 NULL, /* m_traverse */
3344 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003345 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003346};
3347
3348
3349PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003350PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003351{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003352 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003353 return NULL;
3354 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003355 if (PyType_Ready(&FutureType) < 0) {
3356 return NULL;
3357 }
3358 if (PyType_Ready(&FutureIterType) < 0) {
3359 return NULL;
3360 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003361 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003362 return NULL;
3363 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003364 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003365 return NULL;
3366 }
3367 if (PyType_Ready(&TaskType) < 0) {
3368 return NULL;
3369 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003370 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3371 return NULL;
3372 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003373
INADA Naoki9f2ce252016-10-15 15:39:19 +09003374 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003375 if (m == NULL) {
3376 return NULL;
3377 }
3378
3379 Py_INCREF(&FutureType);
3380 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3381 Py_DECREF(&FutureType);
3382 return NULL;
3383 }
3384
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003385 Py_INCREF(&TaskType);
3386 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3387 Py_DECREF(&TaskType);
3388 return NULL;
3389 }
3390
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003391 Py_INCREF(all_tasks);
3392 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3393 Py_DECREF(all_tasks);
3394 return NULL;
3395 }
3396
3397 Py_INCREF(current_tasks);
3398 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3399 Py_DECREF(current_tasks);
3400 return NULL;
3401 }
3402
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003403 return m;
3404}