blob: 89b2fdea0f6321b9731090b752c4533a9021d2a0 [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;
Ben Harper321def82019-10-07 12:19:58 -040036static int module_initialized;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020037
Yury Selivanov9d411c12018-01-23 15:10:03 -050038static PyObject *cached_running_holder;
39static volatile uint64_t cached_running_holder_tsid;
40
Alex Grönholmcca4eec2018-08-09 00:06:47 +030041/* Counter for autogenerated Task names */
42static uint64_t task_name_counter = 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020043
Yury Selivanovca9b36c2017-12-23 15:04:15 -050044/* WeakSet containing all alive tasks. */
45static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020046
47/* Dictionary containing tasks that are currently active in
48 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050049static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090050
Yury Selivanova9d7e552017-12-19 07:18:45 -050051/* An isinstance type cache for the 'is_coroutine()' function. */
52static PyObject *iscoroutine_typecache;
53
INADA Naoki9e4e38e2016-10-09 14:44:47 +090054
INADA Naoki9e4e38e2016-10-09 14:44:47 +090055typedef enum {
56 STATE_PENDING,
57 STATE_CANCELLED,
58 STATE_FINISHED
59} fut_state;
60
Yury Selivanova0c1ba62016-10-28 12:52:37 -040061#define FutureObj_HEAD(prefix) \
62 PyObject_HEAD \
63 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050064 PyObject *prefix##_callback0; \
Yury Selivanov994269c2018-09-27 14:55:55 -040065 PyObject *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040066 PyObject *prefix##_callbacks; \
67 PyObject *prefix##_exception; \
68 PyObject *prefix##_result; \
69 PyObject *prefix##_source_tb; \
70 fut_state prefix##_state; \
71 int prefix##_log_tb; \
72 int prefix##_blocking; \
73 PyObject *dict; \
74 PyObject *prefix##_weakreflist;
75
76typedef struct {
77 FutureObj_HEAD(fut)
78} FutureObj;
79
80typedef struct {
81 FutureObj_HEAD(task)
82 PyObject *task_fut_waiter;
83 PyObject *task_coro;
Alex Grönholmcca4eec2018-08-09 00:06:47 +030084 PyObject *task_name;
Yury Selivanov994269c2018-09-27 14:55:55 -040085 PyObject *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040086 int task_must_cancel;
87 int task_log_destroy_pending;
88} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090089
90typedef struct {
91 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040092 TaskObj *sw_task;
93 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030094} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090095
Yury Selivanova0c1ba62016-10-28 12:52:37 -040096typedef struct {
97 PyObject_HEAD
98 TaskObj *ww_task;
99} TaskWakeupMethWrapper;
100
Yury Selivanov9d411c12018-01-23 15:10:03 -0500101typedef struct {
102 PyObject_HEAD
103 PyObject *rl_loop;
104#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
105 pid_t rl_pid;
106#endif
107} PyRunningLoopHolder;
108
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400109
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500110static PyTypeObject FutureType;
111static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500112static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500113
114
115#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
116#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
117
118#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
119#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
120
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400121#include "clinic/_asynciomodule.c.h"
122
123
124/*[clinic input]
125class _asyncio.Future "FutureObj *" "&Future_Type"
126[clinic start generated code]*/
127/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
128
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500129
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400130/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500131static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900132
Yury Selivanov9d411c12018-01-23 15:10:03 -0500133static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
134
Yury Selivanova70232f2017-12-13 14:49:42 -0500135
136static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500137_is_coroutine(PyObject *coro)
138{
139 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
140 to check if it's another coroutine flavour.
141
142 Do this check after 'future_init()'; in case we need to raise
143 an error, __del__ needs a properly initialized object.
144 */
Jeroen Demeyer196a5302019-07-04 12:31:34 +0200145 PyObject *res = _PyObject_CallOneArg(asyncio_iscoroutine_func, coro);
Yury Selivanova9d7e552017-12-19 07:18:45 -0500146 if (res == NULL) {
147 return -1;
148 }
149
150 int is_res_true = PyObject_IsTrue(res);
151 Py_DECREF(res);
152 if (is_res_true <= 0) {
153 return is_res_true;
154 }
155
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200156 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500157 /* Just in case we don't want to cache more than 100
158 positive types. That shouldn't ever happen, unless
159 someone stressing the system on purpose.
160 */
161 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
162 return -1;
163 }
164 }
165
166 return 1;
167}
168
169
170static inline int
171is_coroutine(PyObject *coro)
172{
173 if (PyCoro_CheckExact(coro)) {
174 return 1;
175 }
176
177 /* Check if `type(coro)` is in the cache.
178 Caching makes is_coroutine() function almost as fast as
179 PyCoro_CheckExact() for non-native coroutine-like objects
180 (like coroutines compiled with Cython).
181
182 asyncio.iscoroutine() has its own type caching mechanism.
183 This cache allows us to avoid the cost of even calling
184 a pure-Python function in 99.9% cases.
185 */
186 int has_it = PySet_Contains(
187 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
188 if (has_it == 0) {
189 /* type(coro) is not in iscoroutine_typecache */
190 return _is_coroutine(coro);
191 }
192
Leo Ariasc3d95082018-02-03 18:36:10 -0600193 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500194 type(coro) is in iscoroutine_typecache
195 */
196 return has_it;
197}
198
199
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500200static PyObject *
201get_future_loop(PyObject *fut)
202{
203 /* Implementation of `asyncio.futures._get_loop` */
204
205 _Py_IDENTIFIER(get_loop);
206 _Py_IDENTIFIER(_loop);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300207 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500208
209 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
210 PyObject *loop = ((FutureObj *)fut)->fut_loop;
211 Py_INCREF(loop);
212 return loop;
213 }
214
Serhiy Storchaka66553542018-05-20 16:30:31 +0300215 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
216 return NULL;
217 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500218 if (getloop != NULL) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200219 PyObject *res = PyObject_CallNoArgs(getloop);
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500220 Py_DECREF(getloop);
221 return res;
222 }
223
224 return _PyObject_GetAttrId(fut, &PyId__loop);
225}
226
227
Yury Selivanova9d7e552017-12-19 07:18:45 -0500228static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500229get_running_loop(PyObject **loop)
230{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500231 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500232
Yury Selivanov9d411c12018-01-23 15:10:03 -0500233 PyThreadState *ts = PyThreadState_Get();
234 if (ts->id == cached_running_holder_tsid && cached_running_holder != NULL) {
235 // Fast path, check the cache.
236 rl = cached_running_holder; // borrowed
237 }
238 else {
239 if (ts->dict == NULL) {
240 goto not_found;
241 }
242
243 rl = _PyDict_GetItemIdWithError(
244 ts->dict, &PyId___asyncio_running_event_loop__); // borrowed
245 if (rl == NULL) {
246 if (PyErr_Occurred()) {
247 goto error;
248 }
249 else {
250 goto not_found;
251 }
252 }
253
254 cached_running_holder = rl; // borrowed
255 cached_running_holder_tsid = ts->id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500256 }
257
Yury Selivanov9d411c12018-01-23 15:10:03 -0500258 assert(Py_TYPE(rl) == &PyRunningLoopHolder_Type);
259 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500260
261 if (running_loop == Py_None) {
262 goto not_found;
263 }
264
Yury Selivanov9d411c12018-01-23 15:10:03 -0500265#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
266 /* On Windows there is no getpid, but there is also no os.fork(),
267 so there is no need for this check.
268 */
269 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
270 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500271 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500272#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500273
Yury Selivanov9d411c12018-01-23 15:10:03 -0500274 Py_INCREF(running_loop);
275 *loop = running_loop;
276 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500277
278not_found:
279 *loop = NULL;
280 return 0;
281
Yury Selivanova70232f2017-12-13 14:49:42 -0500282error:
283 *loop = NULL;
284 return -1;
285}
286
287
288static int
289set_running_loop(PyObject *loop)
290{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500291 cached_running_holder = NULL;
292 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500293
Yury Selivanov9d411c12018-01-23 15:10:03 -0500294 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500295 if (ts_dict == NULL) {
296 PyErr_SetString(
297 PyExc_RuntimeError, "thread-local storage is not available");
298 return -1;
299 }
300
Yury Selivanov9d411c12018-01-23 15:10:03 -0500301 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
302 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500303 return -1;
304 }
305
Yury Selivanova70232f2017-12-13 14:49:42 -0500306 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500307 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
308 {
309 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500310 return -1;
311 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500312 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500313
314 return 0;
315}
316
317
318static PyObject *
319get_event_loop(void)
320{
321 PyObject *loop;
322 PyObject *policy;
323
324 if (get_running_loop(&loop)) {
325 return NULL;
326 }
327 if (loop != NULL) {
328 return loop;
329 }
330
Victor Stinner2ff58a22019-06-17 14:27:23 +0200331 policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy);
Yury Selivanova70232f2017-12-13 14:49:42 -0500332 if (policy == NULL) {
333 return NULL;
334 }
335
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200336 loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
Yury Selivanova70232f2017-12-13 14:49:42 -0500337 Py_DECREF(policy);
338 return loop;
339}
340
341
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900342static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400343call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500344{
345 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500346 PyObject *stack[3];
347 Py_ssize_t nargs;
348
349 if (ctx == NULL) {
350 handle = _PyObject_CallMethodIdObjArgs(
351 loop, &PyId_call_soon, func, arg, NULL);
352 }
353 else {
354 /* Use FASTCALL to pass a keyword-only argument to call_soon */
355
356 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
357 if (callable == NULL) {
358 return -1;
359 }
360
361 /* All refs in 'stack' are borrowed. */
362 nargs = 1;
363 stack[0] = func;
364 if (arg != NULL) {
365 stack[1] = arg;
366 nargs++;
367 }
368 stack[nargs] = (PyObject *)ctx;
369
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200370 handle = _PyObject_Vectorcall(callable, stack, nargs, context_kwname);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500371 Py_DECREF(callable);
372 }
373
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500374 if (handle == NULL) {
375 return -1;
376 }
377 Py_DECREF(handle);
378 return 0;
379}
380
381
382static inline int
383future_is_alive(FutureObj *fut)
384{
385 return fut->fut_loop != NULL;
386}
387
388
389static inline int
390future_ensure_alive(FutureObj *fut)
391{
392 if (!future_is_alive(fut)) {
393 PyErr_SetString(PyExc_RuntimeError,
394 "Future object is not initialized.");
395 return -1;
396 }
397 return 0;
398}
399
400
401#define ENSURE_FUTURE_ALIVE(fut) \
402 do { \
403 assert(Future_Check(fut) || Task_Check(fut)); \
404 if (future_ensure_alive((FutureObj*)fut)) { \
405 return NULL; \
406 } \
407 } while(0);
408
409
410static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400411future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900412{
413 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500414 Py_ssize_t i;
415
416 if (fut->fut_callback0 != NULL) {
417 /* There's a 1st callback */
418
419 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500420 fut->fut_loop, fut->fut_callback0,
421 (PyObject *)fut, fut->fut_context0);
422
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500423 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500424 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500425 if (ret) {
426 /* If an error occurs in pure-Python implementation,
427 all callbacks are cleared. */
428 Py_CLEAR(fut->fut_callbacks);
429 return ret;
430 }
431
432 /* we called the first callback, now try calling
433 callbacks from the 'fut_callbacks' list. */
434 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900435
436 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500437 /* No more callbacks, return. */
438 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900439 }
440
441 len = PyList_GET_SIZE(fut->fut_callbacks);
442 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500443 /* The list of callbacks was empty; clear it and return. */
444 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900445 return 0;
446 }
447
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900448 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500449 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
450 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
451 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900452
Yury Selivanov994269c2018-09-27 14:55:55 -0400453 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500454 /* If an error occurs in pure-Python implementation,
455 all callbacks are cleared. */
456 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900457 return -1;
458 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900459 }
460
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500461 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900462 return 0;
463}
464
Oren Milmand019bc82018-02-13 12:28:33 +0200465
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900466static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400467future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900468{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300469 PyObject *res;
470 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900471 _Py_IDENTIFIER(get_debug);
472
Oren Milmand019bc82018-02-13 12:28:33 +0200473 // Same to FutureObj_clear() but not clearing fut->dict
474 Py_CLEAR(fut->fut_loop);
475 Py_CLEAR(fut->fut_callback0);
476 Py_CLEAR(fut->fut_context0);
477 Py_CLEAR(fut->fut_callbacks);
478 Py_CLEAR(fut->fut_result);
479 Py_CLEAR(fut->fut_exception);
480 Py_CLEAR(fut->fut_source_tb);
481
482 fut->fut_state = STATE_PENDING;
483 fut->fut_log_tb = 0;
484 fut->fut_blocking = 0;
485
Serhiy Storchakabca49392017-09-03 08:10:14 +0300486 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500487 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900488 if (loop == NULL) {
489 return -1;
490 }
491 }
492 else {
493 Py_INCREF(loop);
494 }
Oren Milmand019bc82018-02-13 12:28:33 +0200495 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900496
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200497 res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900498 if (res == NULL) {
499 return -1;
500 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300501 is_true = PyObject_IsTrue(res);
502 Py_DECREF(res);
503 if (is_true < 0) {
504 return -1;
505 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400506 if (is_true && !_Py_IsFinalizing()) {
507 /* Only try to capture the traceback if the interpreter is not being
508 finalized. The original motivation to add a `_Py_IsFinalizing()`
509 call was to prevent SIGSEGV when a Future is created in a __del__
510 method, which is called during the interpreter shutdown and the
511 traceback module is already unloaded.
512 */
Victor Stinner2ff58a22019-06-17 14:27:23 +0200513 fut->fut_source_tb = PyObject_CallNoArgs(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900514 if (fut->fut_source_tb == NULL) {
515 return -1;
516 }
517 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900518
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900519 return 0;
520}
521
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900522static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400523future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900524{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500525 if (future_ensure_alive(fut)) {
526 return NULL;
527 }
528
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900529 if (fut->fut_state != STATE_PENDING) {
530 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
531 return NULL;
532 }
533
Serhiy Storchakabca49392017-09-03 08:10:14 +0300534 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900535 Py_INCREF(res);
536 fut->fut_result = res;
537 fut->fut_state = STATE_FINISHED;
538
Yury Selivanov22feeb82018-01-24 11:31:01 -0500539 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900540 return NULL;
541 }
542 Py_RETURN_NONE;
543}
544
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900545static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400546future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900547{
548 PyObject *exc_val = NULL;
549
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900550 if (fut->fut_state != STATE_PENDING) {
551 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
552 return NULL;
553 }
554
555 if (PyExceptionClass_Check(exc)) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200556 exc_val = PyObject_CallNoArgs(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900557 if (exc_val == NULL) {
558 return NULL;
559 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300560 if (fut->fut_state != STATE_PENDING) {
561 Py_DECREF(exc_val);
562 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
563 return NULL;
564 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900565 }
566 else {
567 exc_val = exc;
568 Py_INCREF(exc_val);
569 }
570 if (!PyExceptionInstance_Check(exc_val)) {
571 Py_DECREF(exc_val);
572 PyErr_SetString(PyExc_TypeError, "invalid exception object");
573 return NULL;
574 }
575 if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
576 Py_DECREF(exc_val);
577 PyErr_SetString(PyExc_TypeError,
578 "StopIteration interacts badly with generators "
579 "and cannot be raised into a Future");
580 return NULL;
581 }
582
Serhiy Storchakabca49392017-09-03 08:10:14 +0300583 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900584 fut->fut_exception = exc_val;
585 fut->fut_state = STATE_FINISHED;
586
Yury Selivanov22feeb82018-01-24 11:31:01 -0500587 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900588 return NULL;
589 }
590
591 fut->fut_log_tb = 1;
592 Py_RETURN_NONE;
593}
594
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400595static int
596future_get_result(FutureObj *fut, PyObject **result)
597{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400598 if (fut->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300599 PyErr_SetNone(asyncio_CancelledError);
600 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400601 }
602
603 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300604 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
605 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400606 }
607
608 fut->fut_log_tb = 0;
609 if (fut->fut_exception != NULL) {
610 Py_INCREF(fut->fut_exception);
611 *result = fut->fut_exception;
612 return 1;
613 }
614
615 Py_INCREF(fut->fut_result);
616 *result = fut->fut_result;
617 return 0;
618}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900619
620static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400621future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900622{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500623 if (!future_is_alive(fut)) {
624 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
625 return NULL;
626 }
627
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900628 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500629 /* The future is done/cancelled, so schedule the callback
630 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500631 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900632 return NULL;
633 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900634 }
635 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500636 /* The future is pending, add a callback.
637
638 Callbacks in the future object are stored as follows:
639
640 callback0 -- a pointer to the first callback
641 callbacks -- a list of 2nd, 3rd, ... callbacks
642
643 Invariants:
644
645 * callbacks != NULL:
646 There are some callbacks in in the list. Just
647 add the new callback to it.
648
649 * callbacks == NULL and callback0 == NULL:
650 This is the first callback. Set it to callback0.
651
652 * callbacks == NULL and callback0 != NULL:
653 This is a second callback. Initialize callbacks
654 with a new list and add the new callback to it.
655 */
656
Yury Selivanovf23746a2018-01-22 19:11:18 -0500657 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500658 Py_INCREF(arg);
659 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500660 Py_INCREF(ctx);
661 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500662 }
663 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500664 PyObject *tup = PyTuple_New(2);
665 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500666 return NULL;
667 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500668 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500669 PyTuple_SET_ITEM(tup, 0, arg);
670 Py_INCREF(ctx);
671 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
672
673 if (fut->fut_callbacks != NULL) {
674 int err = PyList_Append(fut->fut_callbacks, tup);
675 if (err) {
676 Py_DECREF(tup);
677 return NULL;
678 }
679 Py_DECREF(tup);
680 }
681 else {
682 fut->fut_callbacks = PyList_New(1);
683 if (fut->fut_callbacks == NULL) {
684 return NULL;
685 }
686
687 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
688 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900689 }
690 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500691
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900692 Py_RETURN_NONE;
693}
694
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400695static PyObject *
696future_cancel(FutureObj *fut)
697{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000698 fut->fut_log_tb = 0;
699
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400700 if (fut->fut_state != STATE_PENDING) {
701 Py_RETURN_FALSE;
702 }
703 fut->fut_state = STATE_CANCELLED;
704
Yury Selivanov22feeb82018-01-24 11:31:01 -0500705 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400706 return NULL;
707 }
708
709 Py_RETURN_TRUE;
710}
711
712/*[clinic input]
713_asyncio.Future.__init__
714
715 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300716 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400717
718This class is *almost* compatible with concurrent.futures.Future.
719
720 Differences:
721
722 - result() and exception() do not take a timeout argument and
723 raise an exception when the future isn't done yet.
724
725 - Callbacks registered with add_done_callback() are always called
726 via the event loop's call_soon_threadsafe().
727
728 - This class is not compatible with the wait() and as_completed()
729 methods in the concurrent.futures package.
730[clinic start generated code]*/
731
732static int
733_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300734/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400735
736{
737 return future_init(self, loop);
738}
739
740static int
741FutureObj_clear(FutureObj *fut)
742{
743 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500744 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500745 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400746 Py_CLEAR(fut->fut_callbacks);
747 Py_CLEAR(fut->fut_result);
748 Py_CLEAR(fut->fut_exception);
749 Py_CLEAR(fut->fut_source_tb);
750 Py_CLEAR(fut->dict);
751 return 0;
752}
753
754static int
755FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
756{
757 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500758 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500759 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400760 Py_VISIT(fut->fut_callbacks);
761 Py_VISIT(fut->fut_result);
762 Py_VISIT(fut->fut_exception);
763 Py_VISIT(fut->fut_source_tb);
764 Py_VISIT(fut->dict);
765 return 0;
766}
767
768/*[clinic input]
769_asyncio.Future.result
770
771Return the result this future represents.
772
773If the future has been cancelled, raises CancelledError. If the
774future's result isn't yet available, raises InvalidStateError. If
775the future is done and has an exception set, this exception is raised.
776[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900777
778static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400779_asyncio_Future_result_impl(FutureObj *self)
780/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
781{
782 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500783
784 if (!future_is_alive(self)) {
785 PyErr_SetString(asyncio_InvalidStateError,
786 "Future object is not initialized.");
787 return NULL;
788 }
789
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400790 int res = future_get_result(self, &result);
791
792 if (res == -1) {
793 return NULL;
794 }
795
796 if (res == 0) {
797 return result;
798 }
799
800 assert(res == 1);
801
802 PyErr_SetObject(PyExceptionInstance_Class(result), result);
803 Py_DECREF(result);
804 return NULL;
805}
806
807/*[clinic input]
808_asyncio.Future.exception
809
810Return the exception that was set on this future.
811
812The exception (or None if no exception was set) is returned only if
813the future is done. If the future has been cancelled, raises
814CancelledError. If the future isn't done yet, raises
815InvalidStateError.
816[clinic start generated code]*/
817
818static PyObject *
819_asyncio_Future_exception_impl(FutureObj *self)
820/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
821{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500822 if (!future_is_alive(self)) {
823 PyErr_SetString(asyncio_InvalidStateError,
824 "Future object is not initialized.");
825 return NULL;
826 }
827
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400828 if (self->fut_state == STATE_CANCELLED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300829 PyErr_SetNone(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400830 return NULL;
831 }
832
833 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300834 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400835 return NULL;
836 }
837
838 if (self->fut_exception != NULL) {
839 self->fut_log_tb = 0;
840 Py_INCREF(self->fut_exception);
841 return self->fut_exception;
842 }
843
844 Py_RETURN_NONE;
845}
846
847/*[clinic input]
848_asyncio.Future.set_result
849
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500850 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400851 /
852
853Mark the future done and set its result.
854
855If the future is already done when this method is called, raises
856InvalidStateError.
857[clinic start generated code]*/
858
859static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500860_asyncio_Future_set_result(FutureObj *self, PyObject *result)
861/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400862{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500863 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500864 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400865}
866
867/*[clinic input]
868_asyncio.Future.set_exception
869
Serhiy Storchakabca49392017-09-03 08:10:14 +0300870 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400871 /
872
873Mark the future done and set an exception.
874
875If the future is already done when this method is called, raises
876InvalidStateError.
877[clinic start generated code]*/
878
879static PyObject *
880_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300881/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400882{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500883 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400884 return future_set_exception(self, exception);
885}
886
887/*[clinic input]
888_asyncio.Future.add_done_callback
889
Serhiy Storchakabca49392017-09-03 08:10:14 +0300890 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400891 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500892 *
893 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400894
895Add a callback to be run when the future becomes done.
896
897The callback is called with a single argument - the future object. If
898the future is already done when this is called, the callback is
899scheduled with call_soon.
900[clinic start generated code]*/
901
902static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500903_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
904 PyObject *context)
905/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400906{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500907 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400908 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500909 if (context == NULL) {
910 return NULL;
911 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400912 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500913 Py_DECREF(context);
914 return res;
915 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400916 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400917}
918
919/*[clinic input]
920_asyncio.Future.remove_done_callback
921
Serhiy Storchakabca49392017-09-03 08:10:14 +0300922 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400923 /
924
925Remove all instances of a callback from the "call when done" list.
926
927Returns the number of callbacks removed.
928[clinic start generated code]*/
929
930static PyObject *
931_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300932/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900933{
934 PyObject *newlist;
935 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500936 Py_ssize_t cleared_callback0 = 0;
937
938 ENSURE_FUTURE_ALIVE(self)
939
940 if (self->fut_callback0 != NULL) {
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300941 int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500942 if (cmp == -1) {
943 return NULL;
944 }
945 if (cmp == 1) {
946 /* callback0 == fn */
947 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500948 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500949 cleared_callback0 = 1;
950 }
951 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900952
Serhiy Storchakabca49392017-09-03 08:10:14 +0300953 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500954 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300955 }
956
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400957 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900958 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500959 Py_CLEAR(self->fut_callbacks);
960 return PyLong_FromSsize_t(cleared_callback0);
961 }
962
963 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500964 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500965 int cmp = PyObject_RichCompareBool(
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300966 PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500967 if (cmp == -1) {
968 return NULL;
969 }
970 if (cmp == 1) {
971 /* callbacks[0] == fn */
972 Py_CLEAR(self->fut_callbacks);
973 return PyLong_FromSsize_t(1 + cleared_callback0);
974 }
975 /* callbacks[0] != fn and len(callbacks) == 1 */
976 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900977 }
978
979 newlist = PyList_New(len);
980 if (newlist == NULL) {
981 return NULL;
982 }
983
Yury Selivanov84af9032017-03-02 23:46:56 -0500984 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900985 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400986 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300987 Py_INCREF(item);
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300988 ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900989 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400990 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -0400991 PyList_SET_ITEM(newlist, j, item);
992 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +0300993 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -0400994 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300995 ret = PyList_Append(newlist, item);
996 }
997 Py_DECREF(item);
998 if (ret < 0) {
999 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001000 }
1001 }
1002
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001003 if (j == 0) {
1004 Py_CLEAR(self->fut_callbacks);
1005 Py_DECREF(newlist);
1006 return PyLong_FromSsize_t(len + cleared_callback0);
1007 }
1008
Serhiy Storchakabca49392017-09-03 08:10:14 +03001009 if (j < len) {
1010 Py_SIZE(newlist) = j;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001011 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001012 j = PyList_GET_SIZE(newlist);
1013 len = PyList_GET_SIZE(self->fut_callbacks);
1014 if (j != len) {
1015 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1016 goto fail;
1017 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001018 }
1019 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001020 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001021
1022fail:
1023 Py_DECREF(newlist);
1024 return NULL;
1025}
1026
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001027/*[clinic input]
1028_asyncio.Future.cancel
1029
1030Cancel the future and schedule callbacks.
1031
1032If the future is already done or cancelled, return False. Otherwise,
1033change the future's state to cancelled, schedule the callbacks and
1034return True.
1035[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001036
1037static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001038_asyncio_Future_cancel_impl(FutureObj *self)
1039/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001040{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001041 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001042 return future_cancel(self);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001043}
1044
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001045/*[clinic input]
1046_asyncio.Future.cancelled
1047
1048Return True if the future was cancelled.
1049[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001050
1051static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001052_asyncio_Future_cancelled_impl(FutureObj *self)
1053/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001054{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001055 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001056 Py_RETURN_TRUE;
1057 }
1058 else {
1059 Py_RETURN_FALSE;
1060 }
1061}
1062
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001063/*[clinic input]
1064_asyncio.Future.done
1065
1066Return True if the future is done.
1067
1068Done means either that a result / exception are available, or that the
1069future was cancelled.
1070[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001071
1072static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001073_asyncio_Future_done_impl(FutureObj *self)
1074/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001075{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001076 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001077 Py_RETURN_FALSE;
1078 }
1079 else {
1080 Py_RETURN_TRUE;
1081 }
1082}
1083
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001084/*[clinic input]
1085_asyncio.Future.get_loop
1086
1087Return the event loop the Future is bound to.
1088[clinic start generated code]*/
1089
1090static PyObject *
1091_asyncio_Future_get_loop_impl(FutureObj *self)
1092/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1093{
1094 Py_INCREF(self->fut_loop);
1095 return self->fut_loop;
1096}
1097
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001098static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001099FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001100{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001101 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001102 Py_RETURN_TRUE;
1103 }
1104 else {
1105 Py_RETURN_FALSE;
1106 }
1107}
1108
1109static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001110FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001111{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001112 if (future_ensure_alive(fut)) {
1113 return -1;
1114 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001115 if (val == NULL) {
1116 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1117 return -1;
1118 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001119
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001120 int is_true = PyObject_IsTrue(val);
1121 if (is_true < 0) {
1122 return -1;
1123 }
1124 fut->fut_blocking = is_true;
1125 return 0;
1126}
1127
1128static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001129FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001130{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001131 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001132 if (fut->fut_log_tb) {
1133 Py_RETURN_TRUE;
1134 }
1135 else {
1136 Py_RETURN_FALSE;
1137 }
1138}
1139
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001140static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001141FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001142{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001143 if (val == NULL) {
1144 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1145 return -1;
1146 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001147 int is_true = PyObject_IsTrue(val);
1148 if (is_true < 0) {
1149 return -1;
1150 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001151 if (is_true) {
1152 PyErr_SetString(PyExc_ValueError,
1153 "_log_traceback can only be set to False");
1154 return -1;
1155 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001156 fut->fut_log_tb = is_true;
1157 return 0;
1158}
1159
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001160static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001161FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001162{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001163 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001164 Py_RETURN_NONE;
1165 }
1166 Py_INCREF(fut->fut_loop);
1167 return fut->fut_loop;
1168}
1169
1170static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001171FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001172{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001173 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001174
1175 ENSURE_FUTURE_ALIVE(fut)
1176
Yury Selivanovf23746a2018-01-22 19:11:18 -05001177 if (fut->fut_callback0 == NULL) {
1178 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001179 Py_RETURN_NONE;
1180 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001181
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001182 Py_INCREF(fut->fut_callbacks);
1183 return fut->fut_callbacks;
1184 }
1185
Yury Selivanovf23746a2018-01-22 19:11:18 -05001186 Py_ssize_t len = 1;
1187 if (fut->fut_callbacks != NULL) {
1188 len += PyList_GET_SIZE(fut->fut_callbacks);
1189 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001190
Yury Selivanovf23746a2018-01-22 19:11:18 -05001191
1192 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001193 if (new_list == NULL) {
1194 return NULL;
1195 }
1196
Yury Selivanovf23746a2018-01-22 19:11:18 -05001197 PyObject *tup0 = PyTuple_New(2);
1198 if (tup0 == NULL) {
1199 Py_DECREF(new_list);
1200 return NULL;
1201 }
1202
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001203 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001204 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1205 assert(fut->fut_context0 != NULL);
1206 Py_INCREF(fut->fut_context0);
1207 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1208
1209 PyList_SET_ITEM(new_list, 0, tup0);
1210
1211 if (fut->fut_callbacks != NULL) {
1212 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1213 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1214 Py_INCREF(cb);
1215 PyList_SET_ITEM(new_list, i + 1, cb);
1216 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001217 }
1218
1219 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001220}
1221
1222static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001223FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001224{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001225 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001226 if (fut->fut_result == NULL) {
1227 Py_RETURN_NONE;
1228 }
1229 Py_INCREF(fut->fut_result);
1230 return fut->fut_result;
1231}
1232
1233static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001234FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001235{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001236 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001237 if (fut->fut_exception == NULL) {
1238 Py_RETURN_NONE;
1239 }
1240 Py_INCREF(fut->fut_exception);
1241 return fut->fut_exception;
1242}
1243
1244static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001245FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001246{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001247 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001248 Py_RETURN_NONE;
1249 }
1250 Py_INCREF(fut->fut_source_tb);
1251 return fut->fut_source_tb;
1252}
1253
1254static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001255FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001256{
1257 _Py_IDENTIFIER(PENDING);
1258 _Py_IDENTIFIER(CANCELLED);
1259 _Py_IDENTIFIER(FINISHED);
1260 PyObject *ret = NULL;
1261
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001262 ENSURE_FUTURE_ALIVE(fut)
1263
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001264 switch (fut->fut_state) {
1265 case STATE_PENDING:
1266 ret = _PyUnicode_FromId(&PyId_PENDING);
1267 break;
1268 case STATE_CANCELLED:
1269 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1270 break;
1271 case STATE_FINISHED:
1272 ret = _PyUnicode_FromId(&PyId_FINISHED);
1273 break;
1274 default:
1275 assert (0);
1276 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001277 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001278 return ret;
1279}
1280
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001281/*[clinic input]
1282_asyncio.Future._repr_info
1283[clinic start generated code]*/
1284
1285static PyObject *
1286_asyncio_Future__repr_info_impl(FutureObj *self)
1287/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001288{
Jeroen Demeyer196a5302019-07-04 12:31:34 +02001289 return _PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001290}
1291
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001292static PyObject *
1293FutureObj_repr(FutureObj *fut)
1294{
1295 _Py_IDENTIFIER(_repr_info);
1296
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001297 ENSURE_FUTURE_ALIVE(fut)
1298
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001299 PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
1300 &PyId__repr_info);
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
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001846 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1847 &PyId_add, task);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001848 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
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001861 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1862 &PyId_discard, task);
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
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002200 res = _PyObject_CallMethodIdNoArgs(self->task_fut_waiter, &PyId_cancel);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002201 if (res == NULL) {
2202 return NULL;
2203 }
2204
2205 is_true = PyObject_IsTrue(res);
2206 Py_DECREF(res);
2207 if (is_true < 0) {
2208 return NULL;
2209 }
2210
2211 if (is_true) {
2212 Py_RETURN_TRUE;
2213 }
2214 }
2215
2216 self->task_must_cancel = 1;
2217 Py_RETURN_TRUE;
2218}
2219
2220/*[clinic input]
2221_asyncio.Task.get_stack
2222
2223 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002224 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002225
2226Return the list of stack frames for this task's coroutine.
2227
2228If the coroutine is not done, this returns the stack where it is
2229suspended. If the coroutine has completed successfully or was
2230cancelled, this returns an empty list. If the coroutine was
2231terminated by an exception, this returns the list of traceback
2232frames.
2233
2234The frames are always ordered from oldest to newest.
2235
2236The optional limit gives the maximum number of frames to
2237return; by default all available frames are returned. Its
2238meaning differs depending on whether a stack or a traceback is
2239returned: the newest frames of a stack are returned, but the
2240oldest frames of a traceback are returned. (This matches the
2241behavior of the traceback module.)
2242
2243For reasons beyond our control, only one stack frame is
2244returned for a suspended coroutine.
2245[clinic start generated code]*/
2246
2247static PyObject *
2248_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002249/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002250{
2251 return PyObject_CallFunctionObjArgs(
2252 asyncio_task_get_stack_func, self, limit, NULL);
2253}
2254
2255/*[clinic input]
2256_asyncio.Task.print_stack
2257
2258 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002259 limit: object = None
2260 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002261
2262Print the stack or traceback for this task's coroutine.
2263
2264This produces output similar to that of the traceback module,
2265for the frames retrieved by get_stack(). The limit argument
2266is passed to get_stack(). The file argument is an I/O stream
2267to which the output is written; by default output is written
2268to sys.stderr.
2269[clinic start generated code]*/
2270
2271static PyObject *
2272_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2273 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002274/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002275{
2276 return PyObject_CallFunctionObjArgs(
2277 asyncio_task_print_stack_func, self, limit, file, NULL);
2278}
2279
2280/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002281_asyncio.Task.set_result
2282
2283 result: object
2284 /
2285[clinic start generated code]*/
2286
2287static PyObject *
2288_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2289/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2290{
2291 PyErr_SetString(PyExc_RuntimeError,
2292 "Task does not support set_result operation");
2293 return NULL;
2294}
2295
2296/*[clinic input]
2297_asyncio.Task.set_exception
2298
2299 exception: object
2300 /
2301[clinic start generated code]*/
2302
2303static PyObject *
2304_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2305/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2306{
2307 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002308 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002309 return NULL;
2310}
2311
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002312/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002313_asyncio.Task.get_coro
2314[clinic start generated code]*/
2315
2316static PyObject *
2317_asyncio_Task_get_coro_impl(TaskObj *self)
2318/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2319{
2320 Py_INCREF(self->task_coro);
2321 return self->task_coro;
2322}
2323
2324/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002325_asyncio.Task.get_name
2326[clinic start generated code]*/
2327
2328static PyObject *
2329_asyncio_Task_get_name_impl(TaskObj *self)
2330/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2331{
2332 if (self->task_name) {
2333 Py_INCREF(self->task_name);
2334 return self->task_name;
2335 }
2336
2337 Py_RETURN_NONE;
2338}
2339
2340/*[clinic input]
2341_asyncio.Task.set_name
2342
2343 value: object
2344 /
2345[clinic start generated code]*/
2346
2347static PyObject *
2348_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2349/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2350{
Alex Grönholma7548232018-08-09 23:49:49 +03002351 if (!PyUnicode_CheckExact(value)) {
2352 value = PyObject_Str(value);
2353 if (value == NULL) {
2354 return NULL;
2355 }
2356 } else {
2357 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002358 }
2359
Alex Grönholma7548232018-08-09 23:49:49 +03002360 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002361 Py_RETURN_NONE;
2362}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002363
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002364static void
2365TaskObj_finalize(TaskObj *task)
2366{
2367 _Py_IDENTIFIER(call_exception_handler);
2368 _Py_IDENTIFIER(task);
2369 _Py_IDENTIFIER(message);
2370 _Py_IDENTIFIER(source_traceback);
2371
Serhiy Storchakabca49392017-09-03 08:10:14 +03002372 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002373 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002374 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002375 PyObject *error_type, *error_value, *error_traceback;
2376
2377 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2378 goto done;
2379 }
2380
2381 /* Save the current exception, if any. */
2382 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2383
2384 context = PyDict_New();
2385 if (context == NULL) {
2386 goto finally;
2387 }
2388
2389 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2390 if (message == NULL) {
2391 goto finally;
2392 }
2393
2394 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2395 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2396 {
2397 goto finally;
2398 }
2399
2400 if (task->task_source_tb != NULL) {
2401 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2402 task->task_source_tb) < 0)
2403 {
2404 goto finally;
2405 }
2406 }
2407
2408 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2409 if (func != NULL) {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002410 PyObject *res = _PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002411 if (res == NULL) {
2412 PyErr_WriteUnraisable(func);
2413 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002414 else {
2415 Py_DECREF(res);
2416 }
2417 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002418 }
2419
2420finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002421 Py_XDECREF(context);
2422 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002423
2424 /* Restore the saved exception. */
2425 PyErr_Restore(error_type, error_value, error_traceback);
2426
2427done:
2428 FutureObj_finalize((FutureObj*)task);
2429}
2430
2431static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2432
2433static PyMethodDef TaskType_methods[] = {
2434 _ASYNCIO_FUTURE_RESULT_METHODDEF
2435 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002436 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2437 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2438 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2439 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002440 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2441 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002442 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2443 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2444 _ASYNCIO_TASK_CANCEL_METHODDEF
2445 _ASYNCIO_TASK_GET_STACK_METHODDEF
2446 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002447 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002448 _ASYNCIO_TASK_GET_NAME_METHODDEF
2449 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002450 _ASYNCIO_TASK_GET_CORO_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002451 {NULL, NULL} /* Sentinel */
2452};
2453
2454static PyGetSetDef TaskType_getsetlist[] = {
2455 FUTURE_COMMON_GETSETLIST
2456 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2457 (setter)TaskObj_set_log_destroy_pending, NULL},
2458 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2459 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2460 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2461 {NULL} /* Sentinel */
2462};
2463
2464static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002465 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002466 "_asyncio.Task",
2467 sizeof(TaskObj), /* tp_basicsize */
2468 .tp_base = &FutureType,
2469 .tp_dealloc = TaskObj_dealloc,
2470 .tp_as_async = &FutureType_as_async,
2471 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002472 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002473 .tp_doc = _asyncio_Task___init____doc__,
2474 .tp_traverse = (traverseproc)TaskObj_traverse,
2475 .tp_clear = (inquiry)TaskObj_clear,
2476 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2477 .tp_iter = (getiterfunc)future_new_iter,
2478 .tp_methods = TaskType_methods,
2479 .tp_getset = TaskType_getsetlist,
2480 .tp_dictoffset = offsetof(TaskObj, dict),
2481 .tp_init = (initproc)_asyncio_Task___init__,
2482 .tp_new = PyType_GenericNew,
2483 .tp_finalize = (destructor)TaskObj_finalize,
2484};
2485
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002486static void
2487TaskObj_dealloc(PyObject *self)
2488{
2489 TaskObj *task = (TaskObj *)self;
2490
2491 if (Task_CheckExact(self)) {
2492 /* When fut is subclass of Task, finalizer is called from
2493 * subtype_dealloc.
2494 */
2495 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2496 // resurrected.
2497 return;
2498 }
2499 }
2500
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002501 PyObject_GC_UnTrack(self);
2502
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002503 if (task->task_weakreflist != NULL) {
2504 PyObject_ClearWeakRefs(self);
2505 }
2506
2507 (void)TaskObj_clear(task);
2508 Py_TYPE(task)->tp_free(task);
2509}
2510
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002511static int
2512task_call_step_soon(TaskObj *task, PyObject *arg)
2513{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002514 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002515 if (cb == NULL) {
2516 return -1;
2517 }
2518
Yury Selivanovf23746a2018-01-22 19:11:18 -05002519 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002520 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002521 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002522}
2523
2524static PyObject *
2525task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2526{
2527 PyObject* msg;
2528
2529 va_list vargs;
2530#ifdef HAVE_STDARG_PROTOTYPES
2531 va_start(vargs, format);
2532#else
2533 va_start(vargs);
2534#endif
2535 msg = PyUnicode_FromFormatV(format, vargs);
2536 va_end(vargs);
2537
2538 if (msg == NULL) {
2539 return NULL;
2540 }
2541
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002542 PyObject *e = _PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002543 Py_DECREF(msg);
2544 if (e == NULL) {
2545 return NULL;
2546 }
2547
2548 if (task_call_step_soon(task, e) == -1) {
2549 Py_DECREF(e);
2550 return NULL;
2551 }
2552
2553 Py_DECREF(e);
2554 Py_RETURN_NONE;
2555}
2556
2557static PyObject *
2558task_step_impl(TaskObj *task, PyObject *exc)
2559{
2560 int res;
2561 int clear_exc = 0;
2562 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002563 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002564 PyObject *o;
2565
2566 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002567 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002568 "_step(): already done: %R %R",
2569 task,
2570 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002571 goto fail;
2572 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002573
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002574 if (task->task_must_cancel) {
2575 assert(exc != Py_None);
2576
2577 if (exc) {
2578 /* Check if exc is a CancelledError */
2579 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2580 if (res == -1) {
2581 /* An error occurred, abort */
2582 goto fail;
2583 }
2584 if (res == 0) {
2585 /* exc is not CancelledError; reset it to NULL */
2586 exc = NULL;
2587 }
2588 }
2589
2590 if (!exc) {
2591 /* exc was not a CancelledError */
Victor Stinner2ff58a22019-06-17 14:27:23 +02002592 exc = PyObject_CallNoArgs(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002593 if (!exc) {
2594 goto fail;
2595 }
2596 clear_exc = 1;
2597 }
2598
2599 task->task_must_cancel = 0;
2600 }
2601
2602 Py_CLEAR(task->task_fut_waiter);
2603
Serhiy Storchakabca49392017-09-03 08:10:14 +03002604 coro = task->task_coro;
2605 if (coro == NULL) {
2606 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2607 return NULL;
2608 }
2609
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002610 if (exc == NULL) {
2611 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2612 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2613 }
2614 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002615 result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002616 }
2617 }
2618 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002619 result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002620 if (clear_exc) {
2621 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002622 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002623 }
2624 }
2625
2626 if (result == NULL) {
2627 PyObject *et, *ev, *tb;
2628
2629 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2630 /* The error is StopIteration and that means that
2631 the underlying coroutine has resolved */
Yury Selivanovedad4d82019-09-25 03:32:08 -07002632
2633 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002634 if (task->task_must_cancel) {
2635 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002636 task->task_must_cancel = 0;
Yury Selivanovedad4d82019-09-25 03:32:08 -07002637 res = future_cancel((FutureObj*)task);
INADA Naoki991adca2017-05-11 21:18:38 +09002638 }
Yury Selivanovedad4d82019-09-25 03:32:08 -07002639 else {
2640 res = future_set_result((FutureObj*)task, o);
2641 }
2642
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002643 Py_DECREF(o);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002644
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002645 if (res == NULL) {
2646 return NULL;
2647 }
2648 Py_DECREF(res);
2649 Py_RETURN_NONE;
2650 }
2651
2652 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2653 /* CancelledError */
2654 PyErr_Clear();
2655 return future_cancel((FutureObj*)task);
2656 }
2657
2658 /* Some other exception; pop it and call Task.set_exception() */
2659 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002660
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002661 assert(et);
2662 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2663 PyErr_NormalizeException(&et, &ev, &tb);
2664 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002665 if (tb != NULL) {
2666 PyException_SetTraceback(ev, tb);
2667 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002668 o = future_set_exception((FutureObj*)task, ev);
2669 if (!o) {
2670 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002671 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002672 Py_XDECREF(tb);
2673 Py_XDECREF(ev);
2674 goto fail;
2675 }
2676 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002677 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002678
Yury Selivanov431b5402019-05-27 14:45:12 +02002679 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2680 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2681 {
2682 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002683 PyErr_Restore(et, ev, tb);
2684 goto fail;
2685 }
2686
Serhiy Storchakabca49392017-09-03 08:10:14 +03002687 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002688 Py_XDECREF(tb);
2689 Py_XDECREF(ev);
2690
2691 Py_RETURN_NONE;
2692 }
2693
2694 if (result == (PyObject*)task) {
2695 /* We have a task that wants to await on itself */
2696 goto self_await;
2697 }
2698
2699 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2700 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2701 PyObject *wrapper;
2702 PyObject *res;
2703 FutureObj *fut = (FutureObj*)result;
2704
2705 /* Check if `result` future is attached to a different loop */
2706 if (fut->fut_loop != task->task_loop) {
2707 goto different_loop;
2708 }
2709
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002710 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002711 goto yield_insteadof_yf;
2712 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002713
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002714 fut->fut_blocking = 0;
2715
2716 /* result.add_done_callback(task._wakeup) */
2717 wrapper = TaskWakeupMethWrapper_new(task);
2718 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002719 goto fail;
2720 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002721 res = future_add_done_callback(
2722 (FutureObj*)result, wrapper, task->task_context);
2723 Py_DECREF(wrapper);
2724 if (res == NULL) {
2725 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002726 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002727 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002728
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002729 /* task._fut_waiter = result */
2730 task->task_fut_waiter = result; /* no incref is necessary */
2731
2732 if (task->task_must_cancel) {
2733 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002734 int is_true;
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002735 r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002736 if (r == NULL) {
2737 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002738 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002739 is_true = PyObject_IsTrue(r);
2740 Py_DECREF(r);
2741 if (is_true < 0) {
2742 return NULL;
2743 }
2744 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002745 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002746 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002747 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002748
2749 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002750 }
2751
2752 /* Check if `result` is None */
2753 if (result == Py_None) {
2754 /* Bare yield relinquishes control for one event loop iteration. */
2755 if (task_call_step_soon(task, NULL)) {
2756 goto fail;
2757 }
2758 return result;
2759 }
2760
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002761 /* Check if `result` is a Future-compatible object */
2762 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2763 goto fail;
2764 }
2765 if (o != NULL && o != Py_None) {
2766 /* `result` is a Future-compatible object */
2767 PyObject *wrapper;
2768 PyObject *res;
2769
2770 int blocking = PyObject_IsTrue(o);
2771 Py_DECREF(o);
2772 if (blocking < 0) {
2773 goto fail;
2774 }
2775
2776 /* Check if `result` future is attached to a different loop */
2777 PyObject *oloop = get_future_loop(result);
2778 if (oloop == NULL) {
2779 goto fail;
2780 }
2781 if (oloop != task->task_loop) {
2782 Py_DECREF(oloop);
2783 goto different_loop;
2784 }
2785 Py_DECREF(oloop);
2786
2787 if (!blocking) {
2788 goto yield_insteadof_yf;
2789 }
2790
2791 /* result._asyncio_future_blocking = False */
2792 if (_PyObject_SetAttrId(
2793 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2794 goto fail;
2795 }
2796
2797 wrapper = TaskWakeupMethWrapper_new(task);
2798 if (wrapper == NULL) {
2799 goto fail;
2800 }
2801
2802 /* result.add_done_callback(task._wakeup) */
2803 PyObject *add_cb = _PyObject_GetAttrId(
2804 result, &PyId_add_done_callback);
2805 if (add_cb == NULL) {
2806 Py_DECREF(wrapper);
2807 goto fail;
2808 }
2809 PyObject *stack[2];
2810 stack[0] = wrapper;
2811 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002812 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002813 Py_DECREF(add_cb);
2814 Py_DECREF(wrapper);
2815 if (res == NULL) {
2816 goto fail;
2817 }
2818 Py_DECREF(res);
2819
2820 /* task._fut_waiter = result */
2821 task->task_fut_waiter = result; /* no incref is necessary */
2822
2823 if (task->task_must_cancel) {
2824 PyObject *r;
2825 int is_true;
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002826 r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002827 if (r == NULL) {
2828 return NULL;
2829 }
2830 is_true = PyObject_IsTrue(r);
2831 Py_DECREF(r);
2832 if (is_true < 0) {
2833 return NULL;
2834 }
2835 else if (is_true) {
2836 task->task_must_cancel = 0;
2837 }
2838 }
2839
2840 Py_RETURN_NONE;
2841 }
2842
2843 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002844 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002845 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2846 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002847 goto fail;
2848 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002849 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002850 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002851 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002852 task, PyExc_RuntimeError,
2853 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002854 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002855 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002856 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002857 }
2858
2859 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002860 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002861 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002862 Py_DECREF(result);
2863 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002864
2865self_await:
2866 o = task_set_error_soon(
2867 task, PyExc_RuntimeError,
2868 "Task cannot await on itself: %R", task);
2869 Py_DECREF(result);
2870 return o;
2871
2872yield_insteadof_yf:
2873 o = task_set_error_soon(
2874 task, PyExc_RuntimeError,
2875 "yield was used instead of yield from "
2876 "in task %R with %R",
2877 task, result);
2878 Py_DECREF(result);
2879 return o;
2880
2881different_loop:
2882 o = task_set_error_soon(
2883 task, PyExc_RuntimeError,
2884 "Task %R got Future %R attached to a different loop",
2885 task, result);
2886 Py_DECREF(result);
2887 return o;
2888
2889fail:
2890 Py_XDECREF(result);
2891 return NULL;
2892}
2893
2894static PyObject *
2895task_step(TaskObj *task, PyObject *exc)
2896{
2897 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002898
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002899 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002900 return NULL;
2901 }
2902
2903 res = task_step_impl(task, exc);
2904
2905 if (res == NULL) {
2906 PyObject *et, *ev, *tb;
2907 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002908 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002909 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002910 return NULL;
2911 }
2912 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002913 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002914 Py_DECREF(res);
2915 return NULL;
2916 }
2917 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002918 return res;
2919 }
2920 }
2921}
2922
2923static PyObject *
2924task_wakeup(TaskObj *task, PyObject *o)
2925{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002926 PyObject *et, *ev, *tb;
2927 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002928 assert(o);
2929
2930 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2931 PyObject *fut_result = NULL;
2932 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002933
2934 switch(res) {
2935 case -1:
2936 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002937 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002938 case 0:
2939 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002940 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002941 default:
2942 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002943 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002944 Py_DECREF(fut_result);
2945 return result;
2946 }
2947 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002948 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002949 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2950 if (fut_result != NULL) {
2951 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002952 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002953 }
2954 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002955 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002956
2957 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002958 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2959 PyErr_NormalizeException(&et, &ev, &tb);
2960 }
2961
Yury Selivanov22feeb82018-01-24 11:31:01 -05002962 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002963
2964 Py_DECREF(et);
2965 Py_XDECREF(tb);
2966 Py_XDECREF(ev);
2967
2968 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002969}
2970
2971
Yury Selivanova70232f2017-12-13 14:49:42 -05002972/*********************** Functions **************************/
2973
2974
2975/*[clinic input]
2976_asyncio._get_running_loop
2977
2978Return the running event loop or None.
2979
2980This is a low-level function intended to be used by event loops.
2981This function is thread-specific.
2982
2983[clinic start generated code]*/
2984
2985static PyObject *
2986_asyncio__get_running_loop_impl(PyObject *module)
2987/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2988{
2989 PyObject *loop;
2990 if (get_running_loop(&loop)) {
2991 return NULL;
2992 }
2993 if (loop == NULL) {
2994 /* There's no currently running event loop */
2995 Py_RETURN_NONE;
2996 }
2997 return loop;
2998}
2999
3000/*[clinic input]
3001_asyncio._set_running_loop
3002 loop: 'O'
3003 /
3004
3005Set the running event loop.
3006
3007This is a low-level function intended to be used by event loops.
3008This function is thread-specific.
3009[clinic start generated code]*/
3010
3011static PyObject *
3012_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3013/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3014{
3015 if (set_running_loop(loop)) {
3016 return NULL;
3017 }
3018 Py_RETURN_NONE;
3019}
3020
3021/*[clinic input]
3022_asyncio.get_event_loop
3023
3024Return an asyncio event loop.
3025
3026When called from a coroutine or a callback (e.g. scheduled with
3027call_soon or similar API), this function will always return the
3028running event loop.
3029
3030If there is no running event loop set, the function will return
3031the result of `get_event_loop_policy().get_event_loop()` call.
3032[clinic start generated code]*/
3033
3034static PyObject *
3035_asyncio_get_event_loop_impl(PyObject *module)
3036/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3037{
3038 return get_event_loop();
3039}
3040
3041/*[clinic input]
3042_asyncio.get_running_loop
3043
3044Return the running event loop. Raise a RuntimeError if there is none.
3045
3046This function is thread-specific.
3047[clinic start generated code]*/
3048
3049static PyObject *
3050_asyncio_get_running_loop_impl(PyObject *module)
3051/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3052{
3053 PyObject *loop;
3054 if (get_running_loop(&loop)) {
3055 return NULL;
3056 }
3057 if (loop == NULL) {
3058 /* There's no currently running event loop */
3059 PyErr_SetString(
3060 PyExc_RuntimeError, "no running event loop");
3061 }
3062 return loop;
3063}
3064
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003065/*[clinic input]
3066_asyncio._register_task
3067
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003068 task: object
3069
3070Register a new task in asyncio as executed by loop.
3071
3072Returns None.
3073[clinic start generated code]*/
3074
3075static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003076_asyncio__register_task_impl(PyObject *module, PyObject *task)
3077/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003078{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003079 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003080 return NULL;
3081 }
3082 Py_RETURN_NONE;
3083}
3084
3085
3086/*[clinic input]
3087_asyncio._unregister_task
3088
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003089 task: object
3090
3091Unregister a task.
3092
3093Returns None.
3094[clinic start generated code]*/
3095
3096static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003097_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3098/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003099{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003100 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003101 return NULL;
3102 }
3103 Py_RETURN_NONE;
3104}
3105
3106
3107/*[clinic input]
3108_asyncio._enter_task
3109
3110 loop: object
3111 task: object
3112
3113Enter into task execution or resume suspended task.
3114
3115Task belongs to loop.
3116
3117Returns None.
3118[clinic start generated code]*/
3119
3120static PyObject *
3121_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3122/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3123{
3124 if (enter_task(loop, task) < 0) {
3125 return NULL;
3126 }
3127 Py_RETURN_NONE;
3128}
3129
3130
3131/*[clinic input]
3132_asyncio._leave_task
3133
3134 loop: object
3135 task: object
3136
3137Leave task execution or suspend a task.
3138
3139Task belongs to loop.
3140
3141Returns None.
3142[clinic start generated code]*/
3143
3144static PyObject *
3145_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3146/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3147{
3148 if (leave_task(loop, task) < 0) {
3149 return NULL;
3150 }
3151 Py_RETURN_NONE;
3152}
3153
Yury Selivanova70232f2017-12-13 14:49:42 -05003154
Yury Selivanov9d411c12018-01-23 15:10:03 -05003155/*********************** PyRunningLoopHolder ********************/
3156
3157
3158static PyRunningLoopHolder *
3159new_running_loop_holder(PyObject *loop)
3160{
3161 PyRunningLoopHolder *rl = PyObject_New(
3162 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3163 if (rl == NULL) {
3164 return NULL;
3165 }
3166
3167#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3168 rl->rl_pid = getpid();
3169#endif
3170
3171 Py_INCREF(loop);
3172 rl->rl_loop = loop;
3173
3174 return rl;
3175}
3176
3177
3178static void
3179PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3180{
3181 Py_CLEAR(rl->rl_loop);
3182 PyObject_Free(rl);
3183}
3184
3185
3186static PyTypeObject PyRunningLoopHolder_Type = {
3187 PyVarObject_HEAD_INIT(NULL, 0)
3188 "_RunningLoopHolder",
3189 sizeof(PyRunningLoopHolder),
3190 .tp_getattro = PyObject_GenericGetAttr,
3191 .tp_flags = Py_TPFLAGS_DEFAULT,
3192 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3193};
3194
3195
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003196/*********************** Module **************************/
3197
3198
3199static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003200module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003201{
3202 PyObject *next;
3203 PyObject *current;
3204
3205 next = (PyObject*) fi_freelist;
3206 while (next != NULL) {
3207 assert(fi_freelist_len > 0);
3208 fi_freelist_len--;
3209
3210 current = next;
3211 next = (PyObject*) ((futureiterobject*) current)->future;
3212 PyObject_GC_Del(current);
3213 }
3214 assert(fi_freelist_len == 0);
3215 fi_freelist = NULL;
3216}
3217
3218
3219static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003220module_free(void *m)
3221{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003222 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003223 Py_CLEAR(traceback_extract_stack);
3224 Py_CLEAR(asyncio_future_repr_info_func);
3225 Py_CLEAR(asyncio_get_event_loop_policy);
3226 Py_CLEAR(asyncio_iscoroutine_func);
3227 Py_CLEAR(asyncio_task_get_stack_func);
3228 Py_CLEAR(asyncio_task_print_stack_func);
3229 Py_CLEAR(asyncio_task_repr_info_func);
3230 Py_CLEAR(asyncio_InvalidStateError);
3231 Py_CLEAR(asyncio_CancelledError);
3232
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003233 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003234 Py_CLEAR(current_tasks);
3235 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003236
Yury Selivanovf23746a2018-01-22 19:11:18 -05003237 Py_CLEAR(context_kwname);
3238
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003239 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003240}
3241
3242static int
3243module_init(void)
3244{
3245 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003246
3247 asyncio_mod = PyImport_ImportModule("asyncio");
3248 if (asyncio_mod == NULL) {
3249 goto fail;
3250 }
Ben Harper321def82019-10-07 12:19:58 -04003251 if (module_initialized != 0) {
3252 return 0;
3253 }
3254 else {
3255 module_initialized = 1;
3256 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003257
3258 current_tasks = PyDict_New();
3259 if (current_tasks == NULL) {
3260 goto fail;
3261 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003262
Yury Selivanova9d7e552017-12-19 07:18:45 -05003263 iscoroutine_typecache = PySet_New(NULL);
3264 if (iscoroutine_typecache == NULL) {
3265 goto fail;
3266 }
3267
Yury Selivanovf23746a2018-01-22 19:11:18 -05003268
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003269 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003270 if (context_kwname == NULL) {
3271 goto fail;
3272 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003273
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003274#define WITH_MOD(NAME) \
3275 Py_CLEAR(module); \
3276 module = PyImport_ImportModule(NAME); \
3277 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003278 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003279 }
3280
3281#define GET_MOD_ATTR(VAR, NAME) \
3282 VAR = PyObject_GetAttrString(module, NAME); \
3283 if (VAR == NULL) { \
3284 goto fail; \
3285 }
3286
3287 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003288 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003289
3290 WITH_MOD("asyncio.base_futures")
3291 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003292
3293 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003294 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3295 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3296
3297 WITH_MOD("asyncio.base_tasks")
3298 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3299 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3300 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3301
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003302 WITH_MOD("asyncio.coroutines")
3303 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3304
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003305 WITH_MOD("traceback")
3306 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3307
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003308 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003309 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003310 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003311 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003312 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003313 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003314 goto fail;
3315 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003316
Serhiy Storchakabca49392017-09-03 08:10:14 +03003317 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003318 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003319
INADA Naokic411a7d2016-10-18 11:48:14 +09003320fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003321 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003322 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003323 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003324
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003325#undef WITH_MOD
3326#undef GET_MOD_ATTR
3327}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003328
INADA Naokic411a7d2016-10-18 11:48:14 +09003329PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003330
Yury Selivanova70232f2017-12-13 14:49:42 -05003331static PyMethodDef asyncio_methods[] = {
3332 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3333 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3334 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3335 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003336 _ASYNCIO__REGISTER_TASK_METHODDEF
3337 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3338 _ASYNCIO__ENTER_TASK_METHODDEF
3339 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003340 {NULL, NULL}
3341};
3342
INADA Naoki9f2ce252016-10-15 15:39:19 +09003343static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003344 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003345 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003346 module_doc, /* m_doc */
3347 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003348 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003349 NULL, /* m_slots */
3350 NULL, /* m_traverse */
3351 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003352 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003353};
3354
3355
3356PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003357PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003358{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003359 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003360 return NULL;
3361 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003362 if (PyType_Ready(&FutureType) < 0) {
3363 return NULL;
3364 }
3365 if (PyType_Ready(&FutureIterType) < 0) {
3366 return NULL;
3367 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003368 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003369 return NULL;
3370 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003371 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003372 return NULL;
3373 }
3374 if (PyType_Ready(&TaskType) < 0) {
3375 return NULL;
3376 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003377 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3378 return NULL;
3379 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003380
INADA Naoki9f2ce252016-10-15 15:39:19 +09003381 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003382 if (m == NULL) {
3383 return NULL;
3384 }
3385
3386 Py_INCREF(&FutureType);
3387 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3388 Py_DECREF(&FutureType);
3389 return NULL;
3390 }
3391
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003392 Py_INCREF(&TaskType);
3393 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3394 Py_DECREF(&TaskType);
3395 return NULL;
3396 }
3397
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003398 Py_INCREF(all_tasks);
3399 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3400 Py_DECREF(all_tasks);
3401 return NULL;
3402 }
3403
3404 Py_INCREF(current_tasks);
3405 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3406 Py_DECREF(current_tasks);
3407 return NULL;
3408 }
3409
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003410 return m;
3411}