blob: 443acc5723c3b66789db8b6d357c5b478f993889 [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
335 loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
336 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
Victor Stinnerf94d1ee2016-10-29 09:05:39 +0200496 res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
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) {
940 int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ);
941 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(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500965 fn, PyTuple_GET_ITEM(cb_tup, 0), 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);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500987 ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), 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
Serhiy Storchakabca49392017-09-03 08:10:14 +03001298 PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
1299 &PyId__repr_info,
1300 NULL);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001301 if (rinfo == NULL) {
1302 return NULL;
1303 }
1304
Serhiy Storchakabca49392017-09-03 08:10:14 +03001305 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001306 Py_DECREF(rinfo);
1307 if (rinfo_s == NULL) {
1308 return NULL;
1309 }
1310
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001311 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1312 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001313 Py_DECREF(rinfo_s);
1314 return rstr;
1315}
1316
1317static void
1318FutureObj_finalize(FutureObj *fut)
1319{
1320 _Py_IDENTIFIER(call_exception_handler);
1321 _Py_IDENTIFIER(message);
1322 _Py_IDENTIFIER(exception);
1323 _Py_IDENTIFIER(future);
1324 _Py_IDENTIFIER(source_traceback);
1325
Serhiy Storchakabca49392017-09-03 08:10:14 +03001326 PyObject *error_type, *error_value, *error_traceback;
1327 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001328 PyObject *message = NULL;
1329 PyObject *func;
1330
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001331 if (!fut->fut_log_tb) {
1332 return;
1333 }
1334 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001335 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001336
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001337 /* Save the current exception, if any. */
1338 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1339
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001340 context = PyDict_New();
1341 if (context == NULL) {
1342 goto finally;
1343 }
1344
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001345 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001346 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001347 if (message == NULL) {
1348 goto finally;
1349 }
1350
1351 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1352 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1353 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1354 goto finally;
1355 }
1356 if (fut->fut_source_tb != NULL) {
1357 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1358 fut->fut_source_tb) < 0) {
1359 goto finally;
1360 }
1361 }
1362
1363 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1364 if (func != NULL) {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02001365 PyObject *res = _PyObject_CallOneArg(func, context);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001366 if (res == NULL) {
1367 PyErr_WriteUnraisable(func);
1368 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001369 else {
1370 Py_DECREF(res);
1371 }
1372 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001373 }
1374
1375finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001376 Py_XDECREF(context);
1377 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001378
1379 /* Restore the saved exception. */
1380 PyErr_Restore(error_type, error_value, error_traceback);
1381}
1382
1383
1384static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001385 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001386 0, /* am_aiter */
1387 0 /* am_anext */
1388};
1389
1390static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001391 _ASYNCIO_FUTURE_RESULT_METHODDEF
1392 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1393 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1394 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1395 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1396 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1397 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1398 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1399 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001400 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001401 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001402 {NULL, NULL} /* Sentinel */
1403};
1404
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001405#define FUTURE_COMMON_GETSETLIST \
1406 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1407 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1408 (setter)FutureObj_set_blocking, NULL}, \
1409 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1410 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1411 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1412 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001413 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1414 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001415 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001416
1417static PyGetSetDef FutureType_getsetlist[] = {
1418 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001419 {NULL} /* Sentinel */
1420};
1421
1422static void FutureObj_dealloc(PyObject *self);
1423
1424static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001425 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001426 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001427 sizeof(FutureObj), /* tp_basicsize */
1428 .tp_dealloc = FutureObj_dealloc,
1429 .tp_as_async = &FutureType_as_async,
1430 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001431 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001432 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001433 .tp_traverse = (traverseproc)FutureObj_traverse,
1434 .tp_clear = (inquiry)FutureObj_clear,
1435 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001436 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001437 .tp_methods = FutureType_methods,
1438 .tp_getset = FutureType_getsetlist,
1439 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001440 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001441 .tp_new = PyType_GenericNew,
1442 .tp_finalize = (destructor)FutureObj_finalize,
1443};
1444
1445static void
1446FutureObj_dealloc(PyObject *self)
1447{
1448 FutureObj *fut = (FutureObj *)self;
1449
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001450 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001451 /* When fut is subclass of Future, finalizer is called from
1452 * subtype_dealloc.
1453 */
1454 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1455 // resurrected.
1456 return;
1457 }
1458 }
1459
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001460 PyObject_GC_UnTrack(self);
1461
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001462 if (fut->fut_weakreflist != NULL) {
1463 PyObject_ClearWeakRefs(self);
1464 }
1465
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001466 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001467 Py_TYPE(fut)->tp_free(fut);
1468}
1469
1470
1471/*********************** Future Iterator **************************/
1472
1473typedef struct {
1474 PyObject_HEAD
1475 FutureObj *future;
1476} futureiterobject;
1477
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001478
1479#define FI_FREELIST_MAXLEN 255
1480static futureiterobject *fi_freelist = NULL;
1481static Py_ssize_t fi_freelist_len = 0;
1482
1483
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001484static void
1485FutureIter_dealloc(futureiterobject *it)
1486{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001487 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001488 Py_CLEAR(it->future);
1489
1490 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1491 fi_freelist_len++;
1492 it->future = (FutureObj*) fi_freelist;
1493 fi_freelist = it;
1494 }
1495 else {
1496 PyObject_GC_Del(it);
1497 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001498}
1499
1500static PyObject *
1501FutureIter_iternext(futureiterobject *it)
1502{
1503 PyObject *res;
1504 FutureObj *fut = it->future;
1505
1506 if (fut == NULL) {
1507 return NULL;
1508 }
1509
1510 if (fut->fut_state == STATE_PENDING) {
1511 if (!fut->fut_blocking) {
1512 fut->fut_blocking = 1;
1513 Py_INCREF(fut);
1514 return (PyObject *)fut;
1515 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001516 PyErr_SetString(PyExc_RuntimeError,
1517 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001518 return NULL;
1519 }
1520
Serhiy Storchakabca49392017-09-03 08:10:14 +03001521 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001522 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001523 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001524 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001525 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001526 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001527 }
1528
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001529 Py_DECREF(fut);
1530 return NULL;
1531}
1532
1533static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001534FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001535{
INADA Naoki74c17532016-10-25 19:00:45 +09001536 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001537 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001538 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001539 return FutureIter_iternext(self);
1540}
1541
1542static PyObject *
1543FutureIter_throw(futureiterobject *self, PyObject *args)
1544{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001545 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001546 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1547 return NULL;
1548
1549 if (val == Py_None) {
1550 val = NULL;
1551 }
1552 if (tb == Py_None) {
1553 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001554 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1555 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1556 return NULL;
1557 }
1558
1559 Py_INCREF(type);
1560 Py_XINCREF(val);
1561 Py_XINCREF(tb);
1562
1563 if (PyExceptionClass_Check(type)) {
1564 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001565 /* No need to call PyException_SetTraceback since we'll be calling
1566 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001567 } else if (PyExceptionInstance_Check(type)) {
1568 if (val) {
1569 PyErr_SetString(PyExc_TypeError,
1570 "instance exception may not have a separate value");
1571 goto fail;
1572 }
1573 val = type;
1574 type = PyExceptionInstance_Class(type);
1575 Py_INCREF(type);
1576 if (tb == NULL)
1577 tb = PyException_GetTraceback(val);
1578 } else {
1579 PyErr_SetString(PyExc_TypeError,
1580 "exceptions must be classes deriving BaseException or "
1581 "instances of such a class");
1582 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001583 }
1584
1585 Py_CLEAR(self->future);
1586
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001587 PyErr_Restore(type, val, tb);
1588
Serhiy Storchakabca49392017-09-03 08:10:14 +03001589 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001590
1591 fail:
1592 Py_DECREF(type);
1593 Py_XDECREF(val);
1594 Py_XDECREF(tb);
1595 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001596}
1597
1598static PyObject *
1599FutureIter_close(futureiterobject *self, PyObject *arg)
1600{
1601 Py_CLEAR(self->future);
1602 Py_RETURN_NONE;
1603}
1604
1605static int
1606FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1607{
1608 Py_VISIT(it->future);
1609 return 0;
1610}
1611
1612static PyMethodDef FutureIter_methods[] = {
1613 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1614 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1615 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1616 {NULL, NULL} /* Sentinel */
1617};
1618
1619static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001620 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001621 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001622 .tp_basicsize = sizeof(futureiterobject),
1623 .tp_itemsize = 0,
1624 .tp_dealloc = (destructor)FutureIter_dealloc,
1625 .tp_getattro = PyObject_GenericGetAttr,
1626 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1627 .tp_traverse = (traverseproc)FutureIter_traverse,
1628 .tp_iter = PyObject_SelfIter,
1629 .tp_iternext = (iternextfunc)FutureIter_iternext,
1630 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001631};
1632
1633static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001634future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001635{
1636 futureiterobject *it;
1637
1638 if (!PyObject_TypeCheck(fut, &FutureType)) {
1639 PyErr_BadInternalCall();
1640 return NULL;
1641 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001642
1643 ENSURE_FUTURE_ALIVE(fut)
1644
1645 if (fi_freelist_len) {
1646 fi_freelist_len--;
1647 it = fi_freelist;
1648 fi_freelist = (futureiterobject*) it->future;
1649 it->future = NULL;
1650 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001651 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001652 else {
1653 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1654 if (it == NULL) {
1655 return NULL;
1656 }
1657 }
1658
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001659 Py_INCREF(fut);
1660 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001661 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001662 return (PyObject*)it;
1663}
1664
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001665
1666/*********************** Task **************************/
1667
1668
1669/*[clinic input]
1670class _asyncio.Task "TaskObj *" "&Task_Type"
1671[clinic start generated code]*/
1672/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1673
1674static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001675static PyObject * task_wakeup(TaskObj *, PyObject *);
1676static PyObject * task_step(TaskObj *, PyObject *);
1677
1678/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001679
INADA Naokic411a7d2016-10-18 11:48:14 +09001680static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001681TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001682{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001683 Py_CLEAR(o->sw_task);
1684 Py_CLEAR(o->sw_arg);
1685 return 0;
1686}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001687
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001688static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001689TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001690{
1691 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001692 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001693 Py_TYPE(o)->tp_free(o);
1694}
1695
1696static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001697TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001698 PyObject *args, PyObject *kwds)
1699{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001700 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1701 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1702 return NULL;
1703 }
1704 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1705 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1706 return NULL;
1707 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001708 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001709}
1710
1711static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001712TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001713 visitproc visit, void *arg)
1714{
1715 Py_VISIT(o->sw_task);
1716 Py_VISIT(o->sw_arg);
1717 return 0;
1718}
1719
1720static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001721TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001722{
1723 if (o->sw_task) {
1724 Py_INCREF(o->sw_task);
1725 return (PyObject*)o->sw_task;
1726 }
1727 Py_RETURN_NONE;
1728}
1729
Serhiy Storchakabca49392017-09-03 08:10:14 +03001730static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1731 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001732 {NULL} /* Sentinel */
1733};
1734
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001735static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001736 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001737 "TaskStepMethWrapper",
1738 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001739 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001740 .tp_getset = TaskStepMethWrapper_getsetlist,
1741 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1742 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001743 .tp_getattro = PyObject_GenericGetAttr,
1744 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001745 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1746 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001747};
1748
1749static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001750TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001751{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001752 TaskStepMethWrapper *o;
1753 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001754 if (o == NULL) {
1755 return NULL;
1756 }
1757
1758 Py_INCREF(task);
1759 o->sw_task = task;
1760
1761 Py_XINCREF(arg);
1762 o->sw_arg = arg;
1763
1764 PyObject_GC_Track(o);
1765 return (PyObject*) o;
1766}
1767
1768/* ----- Task._wakeup wrapper */
1769
1770static PyObject *
1771TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1772 PyObject *args, PyObject *kwds)
1773{
1774 PyObject *fut;
1775
Serhiy Storchakabca49392017-09-03 08:10:14 +03001776 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1777 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1778 return NULL;
1779 }
1780 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001781 return NULL;
1782 }
1783
Yury Selivanov22feeb82018-01-24 11:31:01 -05001784 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001785}
1786
1787static int
1788TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1789{
1790 Py_CLEAR(o->ww_task);
1791 return 0;
1792}
1793
1794static int
1795TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1796 visitproc visit, void *arg)
1797{
1798 Py_VISIT(o->ww_task);
1799 return 0;
1800}
1801
1802static void
1803TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1804{
1805 PyObject_GC_UnTrack(o);
1806 (void)TaskWakeupMethWrapper_clear(o);
1807 Py_TYPE(o)->tp_free(o);
1808}
1809
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001810static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001811 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001812 "TaskWakeupMethWrapper",
1813 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1814 .tp_itemsize = 0,
1815 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1816 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1817 .tp_getattro = PyObject_GenericGetAttr,
1818 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1819 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1820 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1821};
1822
1823static PyObject *
1824TaskWakeupMethWrapper_new(TaskObj *task)
1825{
1826 TaskWakeupMethWrapper *o;
1827 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1828 if (o == NULL) {
1829 return NULL;
1830 }
1831
1832 Py_INCREF(task);
1833 o->ww_task = task;
1834
1835 PyObject_GC_Track(o);
1836 return (PyObject*) o;
1837}
1838
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001839/* ----- Task introspection helpers */
1840
1841static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001842register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001843{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001844 _Py_IDENTIFIER(add);
1845
1846 PyObject *res = _PyObject_CallMethodIdObjArgs(
1847 all_tasks, &PyId_add, task, NULL);
1848 if (res == NULL) {
1849 return -1;
1850 }
1851 Py_DECREF(res);
1852 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001853}
1854
1855
1856static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001857unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001858{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001859 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001860
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001861 PyObject *res = _PyObject_CallMethodIdObjArgs(
1862 all_tasks, &PyId_discard, task, NULL);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001863 if (res == NULL) {
1864 return -1;
1865 }
1866 Py_DECREF(res);
1867 return 0;
1868}
1869
1870
1871static int
1872enter_task(PyObject *loop, PyObject *task)
1873{
1874 PyObject *item;
1875 Py_hash_t hash;
1876 hash = PyObject_Hash(loop);
1877 if (hash == -1) {
1878 return -1;
1879 }
1880 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1881 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001882 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001883 PyErr_Format(
1884 PyExc_RuntimeError,
1885 "Cannot enter into task %R while another " \
1886 "task %R is being executed.",
1887 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001888 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001889 return -1;
1890 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001891 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001892 return -1;
1893 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001894 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001895}
1896
1897
1898static int
1899leave_task(PyObject *loop, PyObject *task)
1900/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1901{
1902 PyObject *item;
1903 Py_hash_t hash;
1904 hash = PyObject_Hash(loop);
1905 if (hash == -1) {
1906 return -1;
1907 }
1908 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1909 if (item != task) {
1910 if (item == NULL) {
1911 /* Not entered, replace with None */
1912 item = Py_None;
1913 }
1914 PyErr_Format(
1915 PyExc_RuntimeError,
1916 "Leaving task %R does not match the current task %R.",
1917 task, item, NULL);
1918 return -1;
1919 }
1920 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1921}
1922
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001923/* ----- Task */
1924
1925/*[clinic input]
1926_asyncio.Task.__init__
1927
Serhiy Storchakabca49392017-09-03 08:10:14 +03001928 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001929 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001930 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001931 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001932
1933A coroutine wrapped in a Future.
1934[clinic start generated code]*/
1935
1936static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001937_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
1938 PyObject *name)
1939/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001940{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001941 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001942 return -1;
1943 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001944
Yury Selivanova9d7e552017-12-19 07:18:45 -05001945 int is_coro = is_coroutine(coro);
1946 if (is_coro == -1) {
1947 return -1;
1948 }
1949 if (is_coro == 0) {
1950 self->task_log_destroy_pending = 0;
1951 PyErr_Format(PyExc_TypeError,
1952 "a coroutine was expected, got %R",
1953 coro, NULL);
1954 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001955 }
1956
Oren Milmand019bc82018-02-13 12:28:33 +02001957 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001958 if (self->task_context == NULL) {
1959 return -1;
1960 }
1961
Oren Milmand019bc82018-02-13 12:28:33 +02001962 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001963 self->task_must_cancel = 0;
1964 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001965 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001966 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001967
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001968 if (name == Py_None) {
1969 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03001970 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001971 name = PyObject_Str(name);
1972 } else {
1973 Py_INCREF(name);
1974 }
1975 Py_XSETREF(self->task_name, name);
1976 if (self->task_name == NULL) {
1977 return -1;
1978 }
1979
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001980 if (task_call_step_soon(self, NULL)) {
1981 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001982 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001983 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001984}
1985
1986static int
1987TaskObj_clear(TaskObj *task)
1988{
1989 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001990 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001991 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001992 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001993 Py_CLEAR(task->task_fut_waiter);
1994 return 0;
1995}
1996
1997static int
1998TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1999{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002000 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002001 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002002 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002003 Py_VISIT(task->task_fut_waiter);
2004 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2005 return 0;
2006}
2007
2008static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002009TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002010{
2011 if (task->task_log_destroy_pending) {
2012 Py_RETURN_TRUE;
2013 }
2014 else {
2015 Py_RETURN_FALSE;
2016 }
2017}
2018
2019static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002020TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002021{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002022 if (val == NULL) {
2023 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2024 return -1;
2025 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002026 int is_true = PyObject_IsTrue(val);
2027 if (is_true < 0) {
2028 return -1;
2029 }
2030 task->task_log_destroy_pending = is_true;
2031 return 0;
2032}
2033
2034static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002035TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002036{
2037 if (task->task_must_cancel) {
2038 Py_RETURN_TRUE;
2039 }
2040 else {
2041 Py_RETURN_FALSE;
2042 }
2043}
2044
2045static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002046TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002047{
2048 if (task->task_coro) {
2049 Py_INCREF(task->task_coro);
2050 return task->task_coro;
2051 }
2052
2053 Py_RETURN_NONE;
2054}
2055
2056static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002057TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002058{
2059 if (task->task_fut_waiter) {
2060 Py_INCREF(task->task_fut_waiter);
2061 return task->task_fut_waiter;
2062 }
2063
2064 Py_RETURN_NONE;
2065}
2066
2067/*[clinic input]
2068@classmethod
2069_asyncio.Task.current_task
2070
Serhiy Storchakabca49392017-09-03 08:10:14 +03002071 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002072
2073Return the currently running task in an event loop or None.
2074
2075By default the current task for the current event loop is returned.
2076
2077None is returned when called not in the context of a Task.
2078[clinic start generated code]*/
2079
2080static PyObject *
2081_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002082/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002083{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002084 PyObject *ret;
2085 PyObject *current_task_func;
2086
Inada Naokic5c6cda2019-03-22 20:07:32 +09002087 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002088 "Task.current_task() is deprecated, " \
2089 "use asyncio.current_task() instead",
2090 1) < 0) {
2091 return NULL;
2092 }
2093
2094 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2095 if (current_task_func == NULL) {
2096 return NULL;
2097 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002098
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002099 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002100 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002101 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002102 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002103 return NULL;
2104 }
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002105 ret = _PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002106 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002107 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002108 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002109 }
2110 else {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002111 ret = _PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002112 Py_DECREF(current_task_func);
2113 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002114 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002115}
2116
2117/*[clinic input]
2118@classmethod
2119_asyncio.Task.all_tasks
2120
Serhiy Storchakabca49392017-09-03 08:10:14 +03002121 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002122
2123Return a set of all tasks for an event loop.
2124
2125By default all tasks for the current event loop are returned.
2126[clinic start generated code]*/
2127
2128static PyObject *
2129_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002130/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002131{
2132 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002133 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002134
Inada Naokic5c6cda2019-03-22 20:07:32 +09002135 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002136 "Task.all_tasks() is deprecated, " \
2137 "use asyncio.all_tasks() instead",
2138 1) < 0) {
2139 return NULL;
2140 }
2141
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002142 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002143 if (all_tasks_func == NULL) {
2144 return NULL;
2145 }
2146
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002147 res = _PyObject_CallOneArg(all_tasks_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002148 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002149 return res;
2150}
2151
2152/*[clinic input]
2153_asyncio.Task._repr_info
2154[clinic start generated code]*/
2155
2156static PyObject *
2157_asyncio_Task__repr_info_impl(TaskObj *self)
2158/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2159{
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002160 return _PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002161}
2162
2163/*[clinic input]
2164_asyncio.Task.cancel
2165
2166Request that this task cancel itself.
2167
2168This arranges for a CancelledError to be thrown into the
2169wrapped coroutine on the next cycle through the event loop.
2170The coroutine then has a chance to clean up or even deny
2171the request using try/except/finally.
2172
2173Unlike Future.cancel, this does not guarantee that the
2174task will be cancelled: the exception might be caught and
2175acted upon, delaying cancellation of the task or preventing
2176cancellation completely. The task may also return a value or
2177raise a different exception.
2178
2179Immediately after this method is called, Task.cancelled() will
2180not return True (unless the task was already cancelled). A
2181task will be marked as cancelled when the wrapped coroutine
2182terminates with a CancelledError exception (even if cancel()
2183was not called).
2184[clinic start generated code]*/
2185
2186static PyObject *
2187_asyncio_Task_cancel_impl(TaskObj *self)
2188/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2189{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002190 self->task_log_tb = 0;
2191
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002192 if (self->task_state != STATE_PENDING) {
2193 Py_RETURN_FALSE;
2194 }
2195
2196 if (self->task_fut_waiter) {
2197 PyObject *res;
2198 int is_true;
2199
2200 res = _PyObject_CallMethodId(
2201 self->task_fut_waiter, &PyId_cancel, NULL);
2202 if (res == NULL) {
2203 return NULL;
2204 }
2205
2206 is_true = PyObject_IsTrue(res);
2207 Py_DECREF(res);
2208 if (is_true < 0) {
2209 return NULL;
2210 }
2211
2212 if (is_true) {
2213 Py_RETURN_TRUE;
2214 }
2215 }
2216
2217 self->task_must_cancel = 1;
2218 Py_RETURN_TRUE;
2219}
2220
2221/*[clinic input]
2222_asyncio.Task.get_stack
2223
2224 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002225 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002226
2227Return the list of stack frames for this task's coroutine.
2228
2229If the coroutine is not done, this returns the stack where it is
2230suspended. If the coroutine has completed successfully or was
2231cancelled, this returns an empty list. If the coroutine was
2232terminated by an exception, this returns the list of traceback
2233frames.
2234
2235The frames are always ordered from oldest to newest.
2236
2237The optional limit gives the maximum number of frames to
2238return; by default all available frames are returned. Its
2239meaning differs depending on whether a stack or a traceback is
2240returned: the newest frames of a stack are returned, but the
2241oldest frames of a traceback are returned. (This matches the
2242behavior of the traceback module.)
2243
2244For reasons beyond our control, only one stack frame is
2245returned for a suspended coroutine.
2246[clinic start generated code]*/
2247
2248static PyObject *
2249_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002250/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002251{
2252 return PyObject_CallFunctionObjArgs(
2253 asyncio_task_get_stack_func, self, limit, NULL);
2254}
2255
2256/*[clinic input]
2257_asyncio.Task.print_stack
2258
2259 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002260 limit: object = None
2261 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002262
2263Print the stack or traceback for this task's coroutine.
2264
2265This produces output similar to that of the traceback module,
2266for the frames retrieved by get_stack(). The limit argument
2267is passed to get_stack(). The file argument is an I/O stream
2268to which the output is written; by default output is written
2269to sys.stderr.
2270[clinic start generated code]*/
2271
2272static PyObject *
2273_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2274 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002275/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002276{
2277 return PyObject_CallFunctionObjArgs(
2278 asyncio_task_print_stack_func, self, limit, file, NULL);
2279}
2280
2281/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002282_asyncio.Task.set_result
2283
2284 result: object
2285 /
2286[clinic start generated code]*/
2287
2288static PyObject *
2289_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2290/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2291{
2292 PyErr_SetString(PyExc_RuntimeError,
2293 "Task does not support set_result operation");
2294 return NULL;
2295}
2296
2297/*[clinic input]
2298_asyncio.Task.set_exception
2299
2300 exception: object
2301 /
2302[clinic start generated code]*/
2303
2304static PyObject *
2305_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2306/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2307{
2308 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002309 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002310 return NULL;
2311}
2312
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002313/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002314_asyncio.Task.get_coro
2315[clinic start generated code]*/
2316
2317static PyObject *
2318_asyncio_Task_get_coro_impl(TaskObj *self)
2319/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2320{
2321 Py_INCREF(self->task_coro);
2322 return self->task_coro;
2323}
2324
2325/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002326_asyncio.Task.get_name
2327[clinic start generated code]*/
2328
2329static PyObject *
2330_asyncio_Task_get_name_impl(TaskObj *self)
2331/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2332{
2333 if (self->task_name) {
2334 Py_INCREF(self->task_name);
2335 return self->task_name;
2336 }
2337
2338 Py_RETURN_NONE;
2339}
2340
2341/*[clinic input]
2342_asyncio.Task.set_name
2343
2344 value: object
2345 /
2346[clinic start generated code]*/
2347
2348static PyObject *
2349_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2350/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2351{
Alex Grönholma7548232018-08-09 23:49:49 +03002352 if (!PyUnicode_CheckExact(value)) {
2353 value = PyObject_Str(value);
2354 if (value == NULL) {
2355 return NULL;
2356 }
2357 } else {
2358 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002359 }
2360
Alex Grönholma7548232018-08-09 23:49:49 +03002361 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002362 Py_RETURN_NONE;
2363}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002364
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002365static void
2366TaskObj_finalize(TaskObj *task)
2367{
2368 _Py_IDENTIFIER(call_exception_handler);
2369 _Py_IDENTIFIER(task);
2370 _Py_IDENTIFIER(message);
2371 _Py_IDENTIFIER(source_traceback);
2372
Serhiy Storchakabca49392017-09-03 08:10:14 +03002373 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002374 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002375 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002376 PyObject *error_type, *error_value, *error_traceback;
2377
2378 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2379 goto done;
2380 }
2381
2382 /* Save the current exception, if any. */
2383 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2384
2385 context = PyDict_New();
2386 if (context == NULL) {
2387 goto finally;
2388 }
2389
2390 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2391 if (message == NULL) {
2392 goto finally;
2393 }
2394
2395 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2396 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2397 {
2398 goto finally;
2399 }
2400
2401 if (task->task_source_tb != NULL) {
2402 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2403 task->task_source_tb) < 0)
2404 {
2405 goto finally;
2406 }
2407 }
2408
2409 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2410 if (func != NULL) {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002411 PyObject *res = _PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002412 if (res == NULL) {
2413 PyErr_WriteUnraisable(func);
2414 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002415 else {
2416 Py_DECREF(res);
2417 }
2418 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002419 }
2420
2421finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002422 Py_XDECREF(context);
2423 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002424
2425 /* Restore the saved exception. */
2426 PyErr_Restore(error_type, error_value, error_traceback);
2427
2428done:
2429 FutureObj_finalize((FutureObj*)task);
2430}
2431
2432static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2433
2434static PyMethodDef TaskType_methods[] = {
2435 _ASYNCIO_FUTURE_RESULT_METHODDEF
2436 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002437 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2438 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2439 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2440 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002441 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2442 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002443 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2444 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2445 _ASYNCIO_TASK_CANCEL_METHODDEF
2446 _ASYNCIO_TASK_GET_STACK_METHODDEF
2447 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002448 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002449 _ASYNCIO_TASK_GET_NAME_METHODDEF
2450 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002451 _ASYNCIO_TASK_GET_CORO_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002452 {NULL, NULL} /* Sentinel */
2453};
2454
2455static PyGetSetDef TaskType_getsetlist[] = {
2456 FUTURE_COMMON_GETSETLIST
2457 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2458 (setter)TaskObj_set_log_destroy_pending, NULL},
2459 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2460 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2461 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2462 {NULL} /* Sentinel */
2463};
2464
2465static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002466 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002467 "_asyncio.Task",
2468 sizeof(TaskObj), /* tp_basicsize */
2469 .tp_base = &FutureType,
2470 .tp_dealloc = TaskObj_dealloc,
2471 .tp_as_async = &FutureType_as_async,
2472 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002473 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002474 .tp_doc = _asyncio_Task___init____doc__,
2475 .tp_traverse = (traverseproc)TaskObj_traverse,
2476 .tp_clear = (inquiry)TaskObj_clear,
2477 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2478 .tp_iter = (getiterfunc)future_new_iter,
2479 .tp_methods = TaskType_methods,
2480 .tp_getset = TaskType_getsetlist,
2481 .tp_dictoffset = offsetof(TaskObj, dict),
2482 .tp_init = (initproc)_asyncio_Task___init__,
2483 .tp_new = PyType_GenericNew,
2484 .tp_finalize = (destructor)TaskObj_finalize,
2485};
2486
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002487static void
2488TaskObj_dealloc(PyObject *self)
2489{
2490 TaskObj *task = (TaskObj *)self;
2491
2492 if (Task_CheckExact(self)) {
2493 /* When fut is subclass of Task, finalizer is called from
2494 * subtype_dealloc.
2495 */
2496 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2497 // resurrected.
2498 return;
2499 }
2500 }
2501
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002502 PyObject_GC_UnTrack(self);
2503
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002504 if (task->task_weakreflist != NULL) {
2505 PyObject_ClearWeakRefs(self);
2506 }
2507
2508 (void)TaskObj_clear(task);
2509 Py_TYPE(task)->tp_free(task);
2510}
2511
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002512static int
2513task_call_step_soon(TaskObj *task, PyObject *arg)
2514{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002515 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002516 if (cb == NULL) {
2517 return -1;
2518 }
2519
Yury Selivanovf23746a2018-01-22 19:11:18 -05002520 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002521 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002522 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002523}
2524
2525static PyObject *
2526task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2527{
2528 PyObject* msg;
2529
2530 va_list vargs;
2531#ifdef HAVE_STDARG_PROTOTYPES
2532 va_start(vargs, format);
2533#else
2534 va_start(vargs);
2535#endif
2536 msg = PyUnicode_FromFormatV(format, vargs);
2537 va_end(vargs);
2538
2539 if (msg == NULL) {
2540 return NULL;
2541 }
2542
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002543 PyObject *e = _PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002544 Py_DECREF(msg);
2545 if (e == NULL) {
2546 return NULL;
2547 }
2548
2549 if (task_call_step_soon(task, e) == -1) {
2550 Py_DECREF(e);
2551 return NULL;
2552 }
2553
2554 Py_DECREF(e);
2555 Py_RETURN_NONE;
2556}
2557
2558static PyObject *
2559task_step_impl(TaskObj *task, PyObject *exc)
2560{
2561 int res;
2562 int clear_exc = 0;
2563 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002564 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002565 PyObject *o;
2566
2567 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002568 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002569 "_step(): already done: %R %R",
2570 task,
2571 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002572 goto fail;
2573 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002574
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002575 if (task->task_must_cancel) {
2576 assert(exc != Py_None);
2577
2578 if (exc) {
2579 /* Check if exc is a CancelledError */
2580 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2581 if (res == -1) {
2582 /* An error occurred, abort */
2583 goto fail;
2584 }
2585 if (res == 0) {
2586 /* exc is not CancelledError; reset it to NULL */
2587 exc = NULL;
2588 }
2589 }
2590
2591 if (!exc) {
2592 /* exc was not a CancelledError */
Victor Stinner2ff58a22019-06-17 14:27:23 +02002593 exc = PyObject_CallNoArgs(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002594 if (!exc) {
2595 goto fail;
2596 }
2597 clear_exc = 1;
2598 }
2599
2600 task->task_must_cancel = 0;
2601 }
2602
2603 Py_CLEAR(task->task_fut_waiter);
2604
Serhiy Storchakabca49392017-09-03 08:10:14 +03002605 coro = task->task_coro;
2606 if (coro == NULL) {
2607 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2608 return NULL;
2609 }
2610
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002611 if (exc == NULL) {
2612 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2613 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2614 }
2615 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002616 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
2617 Py_None, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002618 }
2619 }
2620 else {
Victor Stinnerb6ed57d2016-12-09 14:24:02 +01002621 result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
2622 exc, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002623 if (clear_exc) {
2624 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002625 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002626 }
2627 }
2628
2629 if (result == NULL) {
2630 PyObject *et, *ev, *tb;
2631
2632 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2633 /* The error is StopIteration and that means that
2634 the underlying coroutine has resolved */
INADA Naoki991adca2017-05-11 21:18:38 +09002635 if (task->task_must_cancel) {
2636 // Task is cancelled right before coro stops.
2637 Py_DECREF(o);
2638 task->task_must_cancel = 0;
2639 et = asyncio_CancelledError;
2640 Py_INCREF(et);
2641 ev = NULL;
2642 tb = NULL;
2643 goto set_exception;
2644 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002645 PyObject *res = future_set_result((FutureObj*)task, o);
2646 Py_DECREF(o);
2647 if (res == NULL) {
2648 return NULL;
2649 }
2650 Py_DECREF(res);
2651 Py_RETURN_NONE;
2652 }
2653
2654 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2655 /* CancelledError */
2656 PyErr_Clear();
2657 return future_cancel((FutureObj*)task);
2658 }
2659
2660 /* Some other exception; pop it and call Task.set_exception() */
2661 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002662
2663set_exception:
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002664 assert(et);
2665 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2666 PyErr_NormalizeException(&et, &ev, &tb);
2667 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002668 if (tb != NULL) {
2669 PyException_SetTraceback(ev, tb);
2670 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002671 o = future_set_exception((FutureObj*)task, ev);
2672 if (!o) {
2673 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002674 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002675 Py_XDECREF(tb);
2676 Py_XDECREF(ev);
2677 goto fail;
2678 }
2679 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002680 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002681
Yury Selivanov431b5402019-05-27 14:45:12 +02002682 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2683 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2684 {
2685 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002686 PyErr_Restore(et, ev, tb);
2687 goto fail;
2688 }
2689
Serhiy Storchakabca49392017-09-03 08:10:14 +03002690 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002691 Py_XDECREF(tb);
2692 Py_XDECREF(ev);
2693
2694 Py_RETURN_NONE;
2695 }
2696
2697 if (result == (PyObject*)task) {
2698 /* We have a task that wants to await on itself */
2699 goto self_await;
2700 }
2701
2702 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2703 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2704 PyObject *wrapper;
2705 PyObject *res;
2706 FutureObj *fut = (FutureObj*)result;
2707
2708 /* Check if `result` future is attached to a different loop */
2709 if (fut->fut_loop != task->task_loop) {
2710 goto different_loop;
2711 }
2712
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002713 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002714 goto yield_insteadof_yf;
2715 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002716
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002717 fut->fut_blocking = 0;
2718
2719 /* result.add_done_callback(task._wakeup) */
2720 wrapper = TaskWakeupMethWrapper_new(task);
2721 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002722 goto fail;
2723 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002724 res = future_add_done_callback(
2725 (FutureObj*)result, wrapper, task->task_context);
2726 Py_DECREF(wrapper);
2727 if (res == NULL) {
2728 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002729 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002730 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002731
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002732 /* task._fut_waiter = result */
2733 task->task_fut_waiter = result; /* no incref is necessary */
2734
2735 if (task->task_must_cancel) {
2736 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002737 int is_true;
Serhiy Storchakaaddf8af2018-10-05 21:20:02 +03002738 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002739 if (r == NULL) {
2740 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002741 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002742 is_true = PyObject_IsTrue(r);
2743 Py_DECREF(r);
2744 if (is_true < 0) {
2745 return NULL;
2746 }
2747 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002748 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002749 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002750 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002751
2752 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002753 }
2754
2755 /* Check if `result` is None */
2756 if (result == Py_None) {
2757 /* Bare yield relinquishes control for one event loop iteration. */
2758 if (task_call_step_soon(task, NULL)) {
2759 goto fail;
2760 }
2761 return result;
2762 }
2763
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002764 /* Check if `result` is a Future-compatible object */
2765 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2766 goto fail;
2767 }
2768 if (o != NULL && o != Py_None) {
2769 /* `result` is a Future-compatible object */
2770 PyObject *wrapper;
2771 PyObject *res;
2772
2773 int blocking = PyObject_IsTrue(o);
2774 Py_DECREF(o);
2775 if (blocking < 0) {
2776 goto fail;
2777 }
2778
2779 /* Check if `result` future is attached to a different loop */
2780 PyObject *oloop = get_future_loop(result);
2781 if (oloop == NULL) {
2782 goto fail;
2783 }
2784 if (oloop != task->task_loop) {
2785 Py_DECREF(oloop);
2786 goto different_loop;
2787 }
2788 Py_DECREF(oloop);
2789
2790 if (!blocking) {
2791 goto yield_insteadof_yf;
2792 }
2793
2794 /* result._asyncio_future_blocking = False */
2795 if (_PyObject_SetAttrId(
2796 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2797 goto fail;
2798 }
2799
2800 wrapper = TaskWakeupMethWrapper_new(task);
2801 if (wrapper == NULL) {
2802 goto fail;
2803 }
2804
2805 /* result.add_done_callback(task._wakeup) */
2806 PyObject *add_cb = _PyObject_GetAttrId(
2807 result, &PyId_add_done_callback);
2808 if (add_cb == NULL) {
2809 Py_DECREF(wrapper);
2810 goto fail;
2811 }
2812 PyObject *stack[2];
2813 stack[0] = wrapper;
2814 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002815 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002816 Py_DECREF(add_cb);
2817 Py_DECREF(wrapper);
2818 if (res == NULL) {
2819 goto fail;
2820 }
2821 Py_DECREF(res);
2822
2823 /* task._fut_waiter = result */
2824 task->task_fut_waiter = result; /* no incref is necessary */
2825
2826 if (task->task_must_cancel) {
2827 PyObject *r;
2828 int is_true;
2829 r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2830 if (r == NULL) {
2831 return NULL;
2832 }
2833 is_true = PyObject_IsTrue(r);
2834 Py_DECREF(r);
2835 if (is_true < 0) {
2836 return NULL;
2837 }
2838 else if (is_true) {
2839 task->task_must_cancel = 0;
2840 }
2841 }
2842
2843 Py_RETURN_NONE;
2844 }
2845
2846 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002847 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002848 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2849 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002850 goto fail;
2851 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002852 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002853 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002854 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002855 task, PyExc_RuntimeError,
2856 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002857 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002858 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002859 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002860 }
2861
2862 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002863 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002864 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002865 Py_DECREF(result);
2866 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002867
2868self_await:
2869 o = task_set_error_soon(
2870 task, PyExc_RuntimeError,
2871 "Task cannot await on itself: %R", task);
2872 Py_DECREF(result);
2873 return o;
2874
2875yield_insteadof_yf:
2876 o = task_set_error_soon(
2877 task, PyExc_RuntimeError,
2878 "yield was used instead of yield from "
2879 "in task %R with %R",
2880 task, result);
2881 Py_DECREF(result);
2882 return o;
2883
2884different_loop:
2885 o = task_set_error_soon(
2886 task, PyExc_RuntimeError,
2887 "Task %R got Future %R attached to a different loop",
2888 task, result);
2889 Py_DECREF(result);
2890 return o;
2891
2892fail:
2893 Py_XDECREF(result);
2894 return NULL;
2895}
2896
2897static PyObject *
2898task_step(TaskObj *task, PyObject *exc)
2899{
2900 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002901
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002902 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002903 return NULL;
2904 }
2905
2906 res = task_step_impl(task, exc);
2907
2908 if (res == NULL) {
2909 PyObject *et, *ev, *tb;
2910 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002911 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002912 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002913 return NULL;
2914 }
2915 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002916 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002917 Py_DECREF(res);
2918 return NULL;
2919 }
2920 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002921 return res;
2922 }
2923 }
2924}
2925
2926static PyObject *
2927task_wakeup(TaskObj *task, PyObject *o)
2928{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002929 PyObject *et, *ev, *tb;
2930 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002931 assert(o);
2932
2933 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2934 PyObject *fut_result = NULL;
2935 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002936
2937 switch(res) {
2938 case -1:
2939 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002940 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002941 case 0:
2942 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002943 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002944 default:
2945 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002946 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002947 Py_DECREF(fut_result);
2948 return result;
2949 }
2950 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002951 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002952 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2953 if (fut_result != NULL) {
2954 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002955 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002956 }
2957 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002958 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002959
2960 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002961 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2962 PyErr_NormalizeException(&et, &ev, &tb);
2963 }
2964
Yury Selivanov22feeb82018-01-24 11:31:01 -05002965 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002966
2967 Py_DECREF(et);
2968 Py_XDECREF(tb);
2969 Py_XDECREF(ev);
2970
2971 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002972}
2973
2974
Yury Selivanova70232f2017-12-13 14:49:42 -05002975/*********************** Functions **************************/
2976
2977
2978/*[clinic input]
2979_asyncio._get_running_loop
2980
2981Return the running event loop or None.
2982
2983This is a low-level function intended to be used by event loops.
2984This function is thread-specific.
2985
2986[clinic start generated code]*/
2987
2988static PyObject *
2989_asyncio__get_running_loop_impl(PyObject *module)
2990/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2991{
2992 PyObject *loop;
2993 if (get_running_loop(&loop)) {
2994 return NULL;
2995 }
2996 if (loop == NULL) {
2997 /* There's no currently running event loop */
2998 Py_RETURN_NONE;
2999 }
3000 return loop;
3001}
3002
3003/*[clinic input]
3004_asyncio._set_running_loop
3005 loop: 'O'
3006 /
3007
3008Set the running event loop.
3009
3010This is a low-level function intended to be used by event loops.
3011This function is thread-specific.
3012[clinic start generated code]*/
3013
3014static PyObject *
3015_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3016/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3017{
3018 if (set_running_loop(loop)) {
3019 return NULL;
3020 }
3021 Py_RETURN_NONE;
3022}
3023
3024/*[clinic input]
3025_asyncio.get_event_loop
3026
3027Return an asyncio event loop.
3028
3029When called from a coroutine or a callback (e.g. scheduled with
3030call_soon or similar API), this function will always return the
3031running event loop.
3032
3033If there is no running event loop set, the function will return
3034the result of `get_event_loop_policy().get_event_loop()` call.
3035[clinic start generated code]*/
3036
3037static PyObject *
3038_asyncio_get_event_loop_impl(PyObject *module)
3039/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3040{
3041 return get_event_loop();
3042}
3043
3044/*[clinic input]
3045_asyncio.get_running_loop
3046
3047Return the running event loop. Raise a RuntimeError if there is none.
3048
3049This function is thread-specific.
3050[clinic start generated code]*/
3051
3052static PyObject *
3053_asyncio_get_running_loop_impl(PyObject *module)
3054/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3055{
3056 PyObject *loop;
3057 if (get_running_loop(&loop)) {
3058 return NULL;
3059 }
3060 if (loop == NULL) {
3061 /* There's no currently running event loop */
3062 PyErr_SetString(
3063 PyExc_RuntimeError, "no running event loop");
3064 }
3065 return loop;
3066}
3067
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003068/*[clinic input]
3069_asyncio._register_task
3070
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003071 task: object
3072
3073Register a new task in asyncio as executed by loop.
3074
3075Returns None.
3076[clinic start generated code]*/
3077
3078static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003079_asyncio__register_task_impl(PyObject *module, PyObject *task)
3080/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003081{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003082 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003083 return NULL;
3084 }
3085 Py_RETURN_NONE;
3086}
3087
3088
3089/*[clinic input]
3090_asyncio._unregister_task
3091
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003092 task: object
3093
3094Unregister a task.
3095
3096Returns None.
3097[clinic start generated code]*/
3098
3099static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003100_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3101/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003102{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003103 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003104 return NULL;
3105 }
3106 Py_RETURN_NONE;
3107}
3108
3109
3110/*[clinic input]
3111_asyncio._enter_task
3112
3113 loop: object
3114 task: object
3115
3116Enter into task execution or resume suspended task.
3117
3118Task belongs to loop.
3119
3120Returns None.
3121[clinic start generated code]*/
3122
3123static PyObject *
3124_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3125/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3126{
3127 if (enter_task(loop, task) < 0) {
3128 return NULL;
3129 }
3130 Py_RETURN_NONE;
3131}
3132
3133
3134/*[clinic input]
3135_asyncio._leave_task
3136
3137 loop: object
3138 task: object
3139
3140Leave task execution or suspend a task.
3141
3142Task belongs to loop.
3143
3144Returns None.
3145[clinic start generated code]*/
3146
3147static PyObject *
3148_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3149/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3150{
3151 if (leave_task(loop, task) < 0) {
3152 return NULL;
3153 }
3154 Py_RETURN_NONE;
3155}
3156
Yury Selivanova70232f2017-12-13 14:49:42 -05003157
Yury Selivanov9d411c12018-01-23 15:10:03 -05003158/*********************** PyRunningLoopHolder ********************/
3159
3160
3161static PyRunningLoopHolder *
3162new_running_loop_holder(PyObject *loop)
3163{
3164 PyRunningLoopHolder *rl = PyObject_New(
3165 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3166 if (rl == NULL) {
3167 return NULL;
3168 }
3169
3170#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3171 rl->rl_pid = getpid();
3172#endif
3173
3174 Py_INCREF(loop);
3175 rl->rl_loop = loop;
3176
3177 return rl;
3178}
3179
3180
3181static void
3182PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3183{
3184 Py_CLEAR(rl->rl_loop);
3185 PyObject_Free(rl);
3186}
3187
3188
3189static PyTypeObject PyRunningLoopHolder_Type = {
3190 PyVarObject_HEAD_INIT(NULL, 0)
3191 "_RunningLoopHolder",
3192 sizeof(PyRunningLoopHolder),
3193 .tp_getattro = PyObject_GenericGetAttr,
3194 .tp_flags = Py_TPFLAGS_DEFAULT,
3195 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3196};
3197
3198
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003199/*********************** Module **************************/
3200
3201
3202static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003203module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003204{
3205 PyObject *next;
3206 PyObject *current;
3207
3208 next = (PyObject*) fi_freelist;
3209 while (next != NULL) {
3210 assert(fi_freelist_len > 0);
3211 fi_freelist_len--;
3212
3213 current = next;
3214 next = (PyObject*) ((futureiterobject*) current)->future;
3215 PyObject_GC_Del(current);
3216 }
3217 assert(fi_freelist_len == 0);
3218 fi_freelist = NULL;
3219}
3220
3221
3222static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003223module_free(void *m)
3224{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003225 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003226 Py_CLEAR(traceback_extract_stack);
3227 Py_CLEAR(asyncio_future_repr_info_func);
3228 Py_CLEAR(asyncio_get_event_loop_policy);
3229 Py_CLEAR(asyncio_iscoroutine_func);
3230 Py_CLEAR(asyncio_task_get_stack_func);
3231 Py_CLEAR(asyncio_task_print_stack_func);
3232 Py_CLEAR(asyncio_task_repr_info_func);
3233 Py_CLEAR(asyncio_InvalidStateError);
3234 Py_CLEAR(asyncio_CancelledError);
3235
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003236 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003237 Py_CLEAR(current_tasks);
3238 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003239
Yury Selivanovf23746a2018-01-22 19:11:18 -05003240 Py_CLEAR(context_kwname);
3241
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003242 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003243}
3244
3245static int
3246module_init(void)
3247{
3248 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003249
3250 asyncio_mod = PyImport_ImportModule("asyncio");
3251 if (asyncio_mod == NULL) {
3252 goto fail;
3253 }
3254
3255 current_tasks = PyDict_New();
3256 if (current_tasks == NULL) {
3257 goto fail;
3258 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003259
Yury Selivanova9d7e552017-12-19 07:18:45 -05003260 iscoroutine_typecache = PySet_New(NULL);
3261 if (iscoroutine_typecache == NULL) {
3262 goto fail;
3263 }
3264
Yury Selivanovf23746a2018-01-22 19:11:18 -05003265
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003266 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003267 if (context_kwname == NULL) {
3268 goto fail;
3269 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003270
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003271#define WITH_MOD(NAME) \
3272 Py_CLEAR(module); \
3273 module = PyImport_ImportModule(NAME); \
3274 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003275 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003276 }
3277
3278#define GET_MOD_ATTR(VAR, NAME) \
3279 VAR = PyObject_GetAttrString(module, NAME); \
3280 if (VAR == NULL) { \
3281 goto fail; \
3282 }
3283
3284 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003285 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003286
3287 WITH_MOD("asyncio.base_futures")
3288 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003289
3290 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003291 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3292 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3293
3294 WITH_MOD("asyncio.base_tasks")
3295 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3296 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3297 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3298
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003299 WITH_MOD("asyncio.coroutines")
3300 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3301
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003302 WITH_MOD("traceback")
3303 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3304
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003305 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003306 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003307 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003308 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003309 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003310 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003311 goto fail;
3312 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003313
Serhiy Storchakabca49392017-09-03 08:10:14 +03003314 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003315 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003316
INADA Naokic411a7d2016-10-18 11:48:14 +09003317fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003318 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003319 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003320 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003321
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003322#undef WITH_MOD
3323#undef GET_MOD_ATTR
3324}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003325
INADA Naokic411a7d2016-10-18 11:48:14 +09003326PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003327
Yury Selivanova70232f2017-12-13 14:49:42 -05003328static PyMethodDef asyncio_methods[] = {
3329 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3330 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3331 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3332 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003333 _ASYNCIO__REGISTER_TASK_METHODDEF
3334 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3335 _ASYNCIO__ENTER_TASK_METHODDEF
3336 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003337 {NULL, NULL}
3338};
3339
INADA Naoki9f2ce252016-10-15 15:39:19 +09003340static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003341 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003342 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003343 module_doc, /* m_doc */
3344 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003345 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003346 NULL, /* m_slots */
3347 NULL, /* m_traverse */
3348 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003349 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003350};
3351
3352
3353PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003354PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003355{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003356 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003357 return NULL;
3358 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003359 if (PyType_Ready(&FutureType) < 0) {
3360 return NULL;
3361 }
3362 if (PyType_Ready(&FutureIterType) < 0) {
3363 return NULL;
3364 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003365 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003366 return NULL;
3367 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003368 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003369 return NULL;
3370 }
3371 if (PyType_Ready(&TaskType) < 0) {
3372 return NULL;
3373 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003374 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3375 return NULL;
3376 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003377
INADA Naoki9f2ce252016-10-15 15:39:19 +09003378 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003379 if (m == NULL) {
3380 return NULL;
3381 }
3382
3383 Py_INCREF(&FutureType);
3384 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3385 Py_DECREF(&FutureType);
3386 return NULL;
3387 }
3388
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003389 Py_INCREF(&TaskType);
3390 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3391 Py_DECREF(&TaskType);
3392 return NULL;
3393 }
3394
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003395 Py_INCREF(all_tasks);
3396 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3397 Py_DECREF(all_tasks);
3398 return NULL;
3399 }
3400
3401 Py_INCREF(current_tasks);
3402 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3403 Py_DECREF(current_tasks);
3404 return NULL;
3405 }
3406
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003407 return m;
3408}