blob: aa46e3cf5640fc3cac97172ed2425ae08a690900 [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{
Andrew Svetlovdad6be52019-11-13 23:36:46 +02001094 ENSURE_FUTURE_ALIVE(self)
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001095 Py_INCREF(self->fut_loop);
1096 return self->fut_loop;
1097}
1098
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001099static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001100FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001101{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001102 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001103 Py_RETURN_TRUE;
1104 }
1105 else {
1106 Py_RETURN_FALSE;
1107 }
1108}
1109
1110static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001111FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001112{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001113 if (future_ensure_alive(fut)) {
1114 return -1;
1115 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001116 if (val == NULL) {
1117 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1118 return -1;
1119 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001120
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001121 int is_true = PyObject_IsTrue(val);
1122 if (is_true < 0) {
1123 return -1;
1124 }
1125 fut->fut_blocking = is_true;
1126 return 0;
1127}
1128
1129static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001130FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001131{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001132 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001133 if (fut->fut_log_tb) {
1134 Py_RETURN_TRUE;
1135 }
1136 else {
1137 Py_RETURN_FALSE;
1138 }
1139}
1140
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001141static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001142FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001143{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001144 if (val == NULL) {
1145 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1146 return -1;
1147 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001148 int is_true = PyObject_IsTrue(val);
1149 if (is_true < 0) {
1150 return -1;
1151 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001152 if (is_true) {
1153 PyErr_SetString(PyExc_ValueError,
1154 "_log_traceback can only be set to False");
1155 return -1;
1156 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001157 fut->fut_log_tb = is_true;
1158 return 0;
1159}
1160
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001161static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001162FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001163{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001164 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001165 Py_RETURN_NONE;
1166 }
1167 Py_INCREF(fut->fut_loop);
1168 return fut->fut_loop;
1169}
1170
1171static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001172FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001173{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001174 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001175
1176 ENSURE_FUTURE_ALIVE(fut)
1177
Yury Selivanovf23746a2018-01-22 19:11:18 -05001178 if (fut->fut_callback0 == NULL) {
1179 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001180 Py_RETURN_NONE;
1181 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001182
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001183 Py_INCREF(fut->fut_callbacks);
1184 return fut->fut_callbacks;
1185 }
1186
Yury Selivanovf23746a2018-01-22 19:11:18 -05001187 Py_ssize_t len = 1;
1188 if (fut->fut_callbacks != NULL) {
1189 len += PyList_GET_SIZE(fut->fut_callbacks);
1190 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001191
Yury Selivanovf23746a2018-01-22 19:11:18 -05001192
1193 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001194 if (new_list == NULL) {
1195 return NULL;
1196 }
1197
Yury Selivanovf23746a2018-01-22 19:11:18 -05001198 PyObject *tup0 = PyTuple_New(2);
1199 if (tup0 == NULL) {
1200 Py_DECREF(new_list);
1201 return NULL;
1202 }
1203
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001204 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001205 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1206 assert(fut->fut_context0 != NULL);
1207 Py_INCREF(fut->fut_context0);
1208 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1209
1210 PyList_SET_ITEM(new_list, 0, tup0);
1211
1212 if (fut->fut_callbacks != NULL) {
1213 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1214 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1215 Py_INCREF(cb);
1216 PyList_SET_ITEM(new_list, i + 1, cb);
1217 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001218 }
1219
1220 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001221}
1222
1223static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001224FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001225{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001226 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001227 if (fut->fut_result == NULL) {
1228 Py_RETURN_NONE;
1229 }
1230 Py_INCREF(fut->fut_result);
1231 return fut->fut_result;
1232}
1233
1234static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001235FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001236{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001237 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001238 if (fut->fut_exception == NULL) {
1239 Py_RETURN_NONE;
1240 }
1241 Py_INCREF(fut->fut_exception);
1242 return fut->fut_exception;
1243}
1244
1245static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001246FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001247{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001248 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001249 Py_RETURN_NONE;
1250 }
1251 Py_INCREF(fut->fut_source_tb);
1252 return fut->fut_source_tb;
1253}
1254
1255static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001256FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001257{
1258 _Py_IDENTIFIER(PENDING);
1259 _Py_IDENTIFIER(CANCELLED);
1260 _Py_IDENTIFIER(FINISHED);
1261 PyObject *ret = NULL;
1262
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001263 ENSURE_FUTURE_ALIVE(fut)
1264
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001265 switch (fut->fut_state) {
1266 case STATE_PENDING:
1267 ret = _PyUnicode_FromId(&PyId_PENDING);
1268 break;
1269 case STATE_CANCELLED:
1270 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1271 break;
1272 case STATE_FINISHED:
1273 ret = _PyUnicode_FromId(&PyId_FINISHED);
1274 break;
1275 default:
1276 assert (0);
1277 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001278 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001279 return ret;
1280}
1281
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001282/*[clinic input]
1283_asyncio.Future._repr_info
1284[clinic start generated code]*/
1285
1286static PyObject *
1287_asyncio_Future__repr_info_impl(FutureObj *self)
1288/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001289{
Jeroen Demeyer196a5302019-07-04 12:31:34 +02001290 return _PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001291}
1292
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001293static PyObject *
1294FutureObj_repr(FutureObj *fut)
1295{
1296 _Py_IDENTIFIER(_repr_info);
1297
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001298 ENSURE_FUTURE_ALIVE(fut)
1299
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001300 PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
1301 &PyId__repr_info);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001302 if (rinfo == NULL) {
1303 return NULL;
1304 }
1305
Serhiy Storchakabca49392017-09-03 08:10:14 +03001306 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001307 Py_DECREF(rinfo);
1308 if (rinfo_s == NULL) {
1309 return NULL;
1310 }
1311
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001312 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1313 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001314 Py_DECREF(rinfo_s);
1315 return rstr;
1316}
1317
1318static void
1319FutureObj_finalize(FutureObj *fut)
1320{
1321 _Py_IDENTIFIER(call_exception_handler);
1322 _Py_IDENTIFIER(message);
1323 _Py_IDENTIFIER(exception);
1324 _Py_IDENTIFIER(future);
1325 _Py_IDENTIFIER(source_traceback);
1326
Serhiy Storchakabca49392017-09-03 08:10:14 +03001327 PyObject *error_type, *error_value, *error_traceback;
1328 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001329 PyObject *message = NULL;
1330 PyObject *func;
1331
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001332 if (!fut->fut_log_tb) {
1333 return;
1334 }
1335 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001336 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001337
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001338 /* Save the current exception, if any. */
1339 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1340
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001341 context = PyDict_New();
1342 if (context == NULL) {
1343 goto finally;
1344 }
1345
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001346 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001347 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001348 if (message == NULL) {
1349 goto finally;
1350 }
1351
1352 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1353 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1354 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1355 goto finally;
1356 }
1357 if (fut->fut_source_tb != NULL) {
1358 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1359 fut->fut_source_tb) < 0) {
1360 goto finally;
1361 }
1362 }
1363
1364 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1365 if (func != NULL) {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02001366 PyObject *res = _PyObject_CallOneArg(func, context);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001367 if (res == NULL) {
1368 PyErr_WriteUnraisable(func);
1369 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001370 else {
1371 Py_DECREF(res);
1372 }
1373 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001374 }
1375
1376finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001377 Py_XDECREF(context);
1378 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001379
1380 /* Restore the saved exception. */
1381 PyErr_Restore(error_type, error_value, error_traceback);
1382}
1383
1384
1385static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001386 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001387 0, /* am_aiter */
1388 0 /* am_anext */
1389};
1390
1391static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001392 _ASYNCIO_FUTURE_RESULT_METHODDEF
1393 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1394 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1395 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1396 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1397 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1398 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1399 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1400 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001401 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001402 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001403 {NULL, NULL} /* Sentinel */
1404};
1405
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001406#define FUTURE_COMMON_GETSETLIST \
1407 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1408 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1409 (setter)FutureObj_set_blocking, NULL}, \
1410 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1411 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1412 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1413 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001414 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1415 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001416 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001417
1418static PyGetSetDef FutureType_getsetlist[] = {
1419 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001420 {NULL} /* Sentinel */
1421};
1422
1423static void FutureObj_dealloc(PyObject *self);
1424
1425static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001426 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001427 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001428 sizeof(FutureObj), /* tp_basicsize */
1429 .tp_dealloc = FutureObj_dealloc,
1430 .tp_as_async = &FutureType_as_async,
1431 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001432 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001433 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001434 .tp_traverse = (traverseproc)FutureObj_traverse,
1435 .tp_clear = (inquiry)FutureObj_clear,
1436 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001437 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001438 .tp_methods = FutureType_methods,
1439 .tp_getset = FutureType_getsetlist,
1440 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001441 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001442 .tp_new = PyType_GenericNew,
1443 .tp_finalize = (destructor)FutureObj_finalize,
1444};
1445
1446static void
1447FutureObj_dealloc(PyObject *self)
1448{
1449 FutureObj *fut = (FutureObj *)self;
1450
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001451 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001452 /* When fut is subclass of Future, finalizer is called from
1453 * subtype_dealloc.
1454 */
1455 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1456 // resurrected.
1457 return;
1458 }
1459 }
1460
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001461 PyObject_GC_UnTrack(self);
1462
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001463 if (fut->fut_weakreflist != NULL) {
1464 PyObject_ClearWeakRefs(self);
1465 }
1466
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001467 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001468 Py_TYPE(fut)->tp_free(fut);
1469}
1470
1471
1472/*********************** Future Iterator **************************/
1473
1474typedef struct {
1475 PyObject_HEAD
1476 FutureObj *future;
1477} futureiterobject;
1478
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001479
1480#define FI_FREELIST_MAXLEN 255
1481static futureiterobject *fi_freelist = NULL;
1482static Py_ssize_t fi_freelist_len = 0;
1483
1484
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001485static void
1486FutureIter_dealloc(futureiterobject *it)
1487{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001488 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001489 Py_CLEAR(it->future);
1490
1491 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1492 fi_freelist_len++;
1493 it->future = (FutureObj*) fi_freelist;
1494 fi_freelist = it;
1495 }
1496 else {
1497 PyObject_GC_Del(it);
1498 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001499}
1500
1501static PyObject *
1502FutureIter_iternext(futureiterobject *it)
1503{
1504 PyObject *res;
1505 FutureObj *fut = it->future;
1506
1507 if (fut == NULL) {
1508 return NULL;
1509 }
1510
1511 if (fut->fut_state == STATE_PENDING) {
1512 if (!fut->fut_blocking) {
1513 fut->fut_blocking = 1;
1514 Py_INCREF(fut);
1515 return (PyObject *)fut;
1516 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001517 PyErr_SetString(PyExc_RuntimeError,
1518 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001519 return NULL;
1520 }
1521
Serhiy Storchakabca49392017-09-03 08:10:14 +03001522 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001523 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001524 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001525 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001526 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001527 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001528 }
1529
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001530 Py_DECREF(fut);
1531 return NULL;
1532}
1533
1534static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001535FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001536{
INADA Naoki74c17532016-10-25 19:00:45 +09001537 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001538 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001539 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001540 return FutureIter_iternext(self);
1541}
1542
1543static PyObject *
1544FutureIter_throw(futureiterobject *self, PyObject *args)
1545{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001546 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001547 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1548 return NULL;
1549
1550 if (val == Py_None) {
1551 val = NULL;
1552 }
1553 if (tb == Py_None) {
1554 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001555 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1556 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1557 return NULL;
1558 }
1559
1560 Py_INCREF(type);
1561 Py_XINCREF(val);
1562 Py_XINCREF(tb);
1563
1564 if (PyExceptionClass_Check(type)) {
1565 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001566 /* No need to call PyException_SetTraceback since we'll be calling
1567 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001568 } else if (PyExceptionInstance_Check(type)) {
1569 if (val) {
1570 PyErr_SetString(PyExc_TypeError,
1571 "instance exception may not have a separate value");
1572 goto fail;
1573 }
1574 val = type;
1575 type = PyExceptionInstance_Class(type);
1576 Py_INCREF(type);
1577 if (tb == NULL)
1578 tb = PyException_GetTraceback(val);
1579 } else {
1580 PyErr_SetString(PyExc_TypeError,
1581 "exceptions must be classes deriving BaseException or "
1582 "instances of such a class");
1583 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001584 }
1585
1586 Py_CLEAR(self->future);
1587
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001588 PyErr_Restore(type, val, tb);
1589
Serhiy Storchakabca49392017-09-03 08:10:14 +03001590 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001591
1592 fail:
1593 Py_DECREF(type);
1594 Py_XDECREF(val);
1595 Py_XDECREF(tb);
1596 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001597}
1598
1599static PyObject *
1600FutureIter_close(futureiterobject *self, PyObject *arg)
1601{
1602 Py_CLEAR(self->future);
1603 Py_RETURN_NONE;
1604}
1605
1606static int
1607FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1608{
1609 Py_VISIT(it->future);
1610 return 0;
1611}
1612
1613static PyMethodDef FutureIter_methods[] = {
1614 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1615 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1616 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1617 {NULL, NULL} /* Sentinel */
1618};
1619
1620static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001621 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001622 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001623 .tp_basicsize = sizeof(futureiterobject),
1624 .tp_itemsize = 0,
1625 .tp_dealloc = (destructor)FutureIter_dealloc,
1626 .tp_getattro = PyObject_GenericGetAttr,
1627 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1628 .tp_traverse = (traverseproc)FutureIter_traverse,
1629 .tp_iter = PyObject_SelfIter,
1630 .tp_iternext = (iternextfunc)FutureIter_iternext,
1631 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001632};
1633
1634static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001635future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001636{
1637 futureiterobject *it;
1638
1639 if (!PyObject_TypeCheck(fut, &FutureType)) {
1640 PyErr_BadInternalCall();
1641 return NULL;
1642 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001643
1644 ENSURE_FUTURE_ALIVE(fut)
1645
1646 if (fi_freelist_len) {
1647 fi_freelist_len--;
1648 it = fi_freelist;
1649 fi_freelist = (futureiterobject*) it->future;
1650 it->future = NULL;
1651 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001652 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001653 else {
1654 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1655 if (it == NULL) {
1656 return NULL;
1657 }
1658 }
1659
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001660 Py_INCREF(fut);
1661 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001662 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001663 return (PyObject*)it;
1664}
1665
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001666
1667/*********************** Task **************************/
1668
1669
1670/*[clinic input]
1671class _asyncio.Task "TaskObj *" "&Task_Type"
1672[clinic start generated code]*/
1673/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1674
1675static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001676static PyObject * task_wakeup(TaskObj *, PyObject *);
1677static PyObject * task_step(TaskObj *, PyObject *);
1678
1679/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001680
INADA Naokic411a7d2016-10-18 11:48:14 +09001681static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001682TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001683{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001684 Py_CLEAR(o->sw_task);
1685 Py_CLEAR(o->sw_arg);
1686 return 0;
1687}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001688
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001689static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001690TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001691{
1692 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001693 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001694 Py_TYPE(o)->tp_free(o);
1695}
1696
1697static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001698TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001699 PyObject *args, PyObject *kwds)
1700{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001701 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1702 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1703 return NULL;
1704 }
1705 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1706 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1707 return NULL;
1708 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001709 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001710}
1711
1712static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001713TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001714 visitproc visit, void *arg)
1715{
1716 Py_VISIT(o->sw_task);
1717 Py_VISIT(o->sw_arg);
1718 return 0;
1719}
1720
1721static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001722TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001723{
1724 if (o->sw_task) {
1725 Py_INCREF(o->sw_task);
1726 return (PyObject*)o->sw_task;
1727 }
1728 Py_RETURN_NONE;
1729}
1730
Serhiy Storchakabca49392017-09-03 08:10:14 +03001731static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1732 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001733 {NULL} /* Sentinel */
1734};
1735
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001736static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001737 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001738 "TaskStepMethWrapper",
1739 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001740 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001741 .tp_getset = TaskStepMethWrapper_getsetlist,
1742 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1743 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001744 .tp_getattro = PyObject_GenericGetAttr,
1745 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001746 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1747 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001748};
1749
1750static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001751TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001752{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001753 TaskStepMethWrapper *o;
1754 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001755 if (o == NULL) {
1756 return NULL;
1757 }
1758
1759 Py_INCREF(task);
1760 o->sw_task = task;
1761
1762 Py_XINCREF(arg);
1763 o->sw_arg = arg;
1764
1765 PyObject_GC_Track(o);
1766 return (PyObject*) o;
1767}
1768
1769/* ----- Task._wakeup wrapper */
1770
1771static PyObject *
1772TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1773 PyObject *args, PyObject *kwds)
1774{
1775 PyObject *fut;
1776
Serhiy Storchakabca49392017-09-03 08:10:14 +03001777 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1778 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1779 return NULL;
1780 }
1781 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001782 return NULL;
1783 }
1784
Yury Selivanov22feeb82018-01-24 11:31:01 -05001785 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001786}
1787
1788static int
1789TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1790{
1791 Py_CLEAR(o->ww_task);
1792 return 0;
1793}
1794
1795static int
1796TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1797 visitproc visit, void *arg)
1798{
1799 Py_VISIT(o->ww_task);
1800 return 0;
1801}
1802
1803static void
1804TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1805{
1806 PyObject_GC_UnTrack(o);
1807 (void)TaskWakeupMethWrapper_clear(o);
1808 Py_TYPE(o)->tp_free(o);
1809}
1810
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001811static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001812 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001813 "TaskWakeupMethWrapper",
1814 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1815 .tp_itemsize = 0,
1816 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1817 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1818 .tp_getattro = PyObject_GenericGetAttr,
1819 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1820 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1821 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1822};
1823
1824static PyObject *
1825TaskWakeupMethWrapper_new(TaskObj *task)
1826{
1827 TaskWakeupMethWrapper *o;
1828 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1829 if (o == NULL) {
1830 return NULL;
1831 }
1832
1833 Py_INCREF(task);
1834 o->ww_task = task;
1835
1836 PyObject_GC_Track(o);
1837 return (PyObject*) o;
1838}
1839
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001840/* ----- Task introspection helpers */
1841
1842static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001843register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001844{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001845 _Py_IDENTIFIER(add);
1846
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001847 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1848 &PyId_add, task);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001849 if (res == NULL) {
1850 return -1;
1851 }
1852 Py_DECREF(res);
1853 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001854}
1855
1856
1857static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001858unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001859{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001860 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001861
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001862 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1863 &PyId_discard, task);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001864 if (res == NULL) {
1865 return -1;
1866 }
1867 Py_DECREF(res);
1868 return 0;
1869}
1870
1871
1872static int
1873enter_task(PyObject *loop, PyObject *task)
1874{
1875 PyObject *item;
1876 Py_hash_t hash;
1877 hash = PyObject_Hash(loop);
1878 if (hash == -1) {
1879 return -1;
1880 }
1881 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1882 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001883 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001884 PyErr_Format(
1885 PyExc_RuntimeError,
1886 "Cannot enter into task %R while another " \
1887 "task %R is being executed.",
1888 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001889 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001890 return -1;
1891 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001892 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001893 return -1;
1894 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001895 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001896}
1897
1898
1899static int
1900leave_task(PyObject *loop, PyObject *task)
1901/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1902{
1903 PyObject *item;
1904 Py_hash_t hash;
1905 hash = PyObject_Hash(loop);
1906 if (hash == -1) {
1907 return -1;
1908 }
1909 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1910 if (item != task) {
1911 if (item == NULL) {
1912 /* Not entered, replace with None */
1913 item = Py_None;
1914 }
1915 PyErr_Format(
1916 PyExc_RuntimeError,
1917 "Leaving task %R does not match the current task %R.",
1918 task, item, NULL);
1919 return -1;
1920 }
1921 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1922}
1923
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001924/* ----- Task */
1925
1926/*[clinic input]
1927_asyncio.Task.__init__
1928
Serhiy Storchakabca49392017-09-03 08:10:14 +03001929 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001930 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001931 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001932 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001933
1934A coroutine wrapped in a Future.
1935[clinic start generated code]*/
1936
1937static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001938_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
1939 PyObject *name)
1940/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001941{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001942 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001943 return -1;
1944 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001945
Yury Selivanova9d7e552017-12-19 07:18:45 -05001946 int is_coro = is_coroutine(coro);
1947 if (is_coro == -1) {
1948 return -1;
1949 }
1950 if (is_coro == 0) {
1951 self->task_log_destroy_pending = 0;
1952 PyErr_Format(PyExc_TypeError,
1953 "a coroutine was expected, got %R",
1954 coro, NULL);
1955 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001956 }
1957
Oren Milmand019bc82018-02-13 12:28:33 +02001958 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001959 if (self->task_context == NULL) {
1960 return -1;
1961 }
1962
Oren Milmand019bc82018-02-13 12:28:33 +02001963 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001964 self->task_must_cancel = 0;
1965 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001966 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001967 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001968
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001969 if (name == Py_None) {
1970 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03001971 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001972 name = PyObject_Str(name);
1973 } else {
1974 Py_INCREF(name);
1975 }
1976 Py_XSETREF(self->task_name, name);
1977 if (self->task_name == NULL) {
1978 return -1;
1979 }
1980
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001981 if (task_call_step_soon(self, NULL)) {
1982 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09001983 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001984 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001985}
1986
1987static int
1988TaskObj_clear(TaskObj *task)
1989{
1990 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001991 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001992 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001993 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001994 Py_CLEAR(task->task_fut_waiter);
1995 return 0;
1996}
1997
1998static int
1999TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2000{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002001 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002002 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002003 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002004 Py_VISIT(task->task_fut_waiter);
2005 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2006 return 0;
2007}
2008
2009static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002010TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002011{
2012 if (task->task_log_destroy_pending) {
2013 Py_RETURN_TRUE;
2014 }
2015 else {
2016 Py_RETURN_FALSE;
2017 }
2018}
2019
2020static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002021TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002022{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002023 if (val == NULL) {
2024 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2025 return -1;
2026 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002027 int is_true = PyObject_IsTrue(val);
2028 if (is_true < 0) {
2029 return -1;
2030 }
2031 task->task_log_destroy_pending = is_true;
2032 return 0;
2033}
2034
2035static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002036TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002037{
2038 if (task->task_must_cancel) {
2039 Py_RETURN_TRUE;
2040 }
2041 else {
2042 Py_RETURN_FALSE;
2043 }
2044}
2045
2046static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002047TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002048{
2049 if (task->task_coro) {
2050 Py_INCREF(task->task_coro);
2051 return task->task_coro;
2052 }
2053
2054 Py_RETURN_NONE;
2055}
2056
2057static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002058TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002059{
2060 if (task->task_fut_waiter) {
2061 Py_INCREF(task->task_fut_waiter);
2062 return task->task_fut_waiter;
2063 }
2064
2065 Py_RETURN_NONE;
2066}
2067
2068/*[clinic input]
2069@classmethod
2070_asyncio.Task.current_task
2071
Serhiy Storchakabca49392017-09-03 08:10:14 +03002072 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002073
2074Return the currently running task in an event loop or None.
2075
2076By default the current task for the current event loop is returned.
2077
2078None is returned when called not in the context of a Task.
2079[clinic start generated code]*/
2080
2081static PyObject *
2082_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002083/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002084{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002085 PyObject *ret;
2086 PyObject *current_task_func;
2087
Inada Naokic5c6cda2019-03-22 20:07:32 +09002088 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002089 "Task.current_task() is deprecated, " \
2090 "use asyncio.current_task() instead",
2091 1) < 0) {
2092 return NULL;
2093 }
2094
2095 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2096 if (current_task_func == NULL) {
2097 return NULL;
2098 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002099
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002100 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002101 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002102 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002103 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002104 return NULL;
2105 }
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002106 ret = _PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002107 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002108 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002109 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002110 }
2111 else {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002112 ret = _PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002113 Py_DECREF(current_task_func);
2114 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002115 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002116}
2117
2118/*[clinic input]
2119@classmethod
2120_asyncio.Task.all_tasks
2121
Serhiy Storchakabca49392017-09-03 08:10:14 +03002122 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002123
2124Return a set of all tasks for an event loop.
2125
2126By default all tasks for the current event loop are returned.
2127[clinic start generated code]*/
2128
2129static PyObject *
2130_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002131/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002132{
2133 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002134 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002135
Inada Naokic5c6cda2019-03-22 20:07:32 +09002136 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002137 "Task.all_tasks() is deprecated, " \
2138 "use asyncio.all_tasks() instead",
2139 1) < 0) {
2140 return NULL;
2141 }
2142
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002143 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002144 if (all_tasks_func == NULL) {
2145 return NULL;
2146 }
2147
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002148 res = _PyObject_CallOneArg(all_tasks_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002149 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002150 return res;
2151}
2152
2153/*[clinic input]
2154_asyncio.Task._repr_info
2155[clinic start generated code]*/
2156
2157static PyObject *
2158_asyncio_Task__repr_info_impl(TaskObj *self)
2159/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2160{
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002161 return _PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002162}
2163
2164/*[clinic input]
2165_asyncio.Task.cancel
2166
2167Request that this task cancel itself.
2168
2169This arranges for a CancelledError to be thrown into the
2170wrapped coroutine on the next cycle through the event loop.
2171The coroutine then has a chance to clean up or even deny
2172the request using try/except/finally.
2173
2174Unlike Future.cancel, this does not guarantee that the
2175task will be cancelled: the exception might be caught and
2176acted upon, delaying cancellation of the task or preventing
2177cancellation completely. The task may also return a value or
2178raise a different exception.
2179
2180Immediately after this method is called, Task.cancelled() will
2181not return True (unless the task was already cancelled). A
2182task will be marked as cancelled when the wrapped coroutine
2183terminates with a CancelledError exception (even if cancel()
2184was not called).
2185[clinic start generated code]*/
2186
2187static PyObject *
2188_asyncio_Task_cancel_impl(TaskObj *self)
2189/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2190{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002191 self->task_log_tb = 0;
2192
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002193 if (self->task_state != STATE_PENDING) {
2194 Py_RETURN_FALSE;
2195 }
2196
2197 if (self->task_fut_waiter) {
2198 PyObject *res;
2199 int is_true;
2200
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002201 res = _PyObject_CallMethodIdNoArgs(self->task_fut_waiter, &PyId_cancel);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002202 if (res == NULL) {
2203 return NULL;
2204 }
2205
2206 is_true = PyObject_IsTrue(res);
2207 Py_DECREF(res);
2208 if (is_true < 0) {
2209 return NULL;
2210 }
2211
2212 if (is_true) {
2213 Py_RETURN_TRUE;
2214 }
2215 }
2216
2217 self->task_must_cancel = 1;
2218 Py_RETURN_TRUE;
2219}
2220
2221/*[clinic input]
2222_asyncio.Task.get_stack
2223
2224 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002225 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002226
2227Return the list of stack frames for this task's coroutine.
2228
2229If the coroutine is not done, this returns the stack where it is
2230suspended. If the coroutine has completed successfully or was
2231cancelled, this returns an empty list. If the coroutine was
2232terminated by an exception, this returns the list of traceback
2233frames.
2234
2235The frames are always ordered from oldest to newest.
2236
2237The optional limit gives the maximum number of frames to
2238return; by default all available frames are returned. Its
2239meaning differs depending on whether a stack or a traceback is
2240returned: the newest frames of a stack are returned, but the
2241oldest frames of a traceback are returned. (This matches the
2242behavior of the traceback module.)
2243
2244For reasons beyond our control, only one stack frame is
2245returned for a suspended coroutine.
2246[clinic start generated code]*/
2247
2248static PyObject *
2249_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002250/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002251{
2252 return PyObject_CallFunctionObjArgs(
2253 asyncio_task_get_stack_func, self, limit, NULL);
2254}
2255
2256/*[clinic input]
2257_asyncio.Task.print_stack
2258
2259 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002260 limit: object = None
2261 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002262
2263Print the stack or traceback for this task's coroutine.
2264
2265This produces output similar to that of the traceback module,
2266for the frames retrieved by get_stack(). The limit argument
2267is passed to get_stack(). The file argument is an I/O stream
2268to which the output is written; by default output is written
2269to sys.stderr.
2270[clinic start generated code]*/
2271
2272static PyObject *
2273_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2274 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002275/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002276{
2277 return PyObject_CallFunctionObjArgs(
2278 asyncio_task_print_stack_func, self, limit, file, NULL);
2279}
2280
2281/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002282_asyncio.Task.set_result
2283
2284 result: object
2285 /
2286[clinic start generated code]*/
2287
2288static PyObject *
2289_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2290/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2291{
2292 PyErr_SetString(PyExc_RuntimeError,
2293 "Task does not support set_result operation");
2294 return NULL;
2295}
2296
2297/*[clinic input]
2298_asyncio.Task.set_exception
2299
2300 exception: object
2301 /
2302[clinic start generated code]*/
2303
2304static PyObject *
2305_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2306/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2307{
2308 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002309 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002310 return NULL;
2311}
2312
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002313/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002314_asyncio.Task.get_coro
2315[clinic start generated code]*/
2316
2317static PyObject *
2318_asyncio_Task_get_coro_impl(TaskObj *self)
2319/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2320{
2321 Py_INCREF(self->task_coro);
2322 return self->task_coro;
2323}
2324
2325/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002326_asyncio.Task.get_name
2327[clinic start generated code]*/
2328
2329static PyObject *
2330_asyncio_Task_get_name_impl(TaskObj *self)
2331/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2332{
2333 if (self->task_name) {
2334 Py_INCREF(self->task_name);
2335 return self->task_name;
2336 }
2337
2338 Py_RETURN_NONE;
2339}
2340
2341/*[clinic input]
2342_asyncio.Task.set_name
2343
2344 value: object
2345 /
2346[clinic start generated code]*/
2347
2348static PyObject *
2349_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2350/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2351{
Alex Grönholma7548232018-08-09 23:49:49 +03002352 if (!PyUnicode_CheckExact(value)) {
2353 value = PyObject_Str(value);
2354 if (value == NULL) {
2355 return NULL;
2356 }
2357 } else {
2358 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002359 }
2360
Alex Grönholma7548232018-08-09 23:49:49 +03002361 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002362 Py_RETURN_NONE;
2363}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002364
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002365static void
2366TaskObj_finalize(TaskObj *task)
2367{
2368 _Py_IDENTIFIER(call_exception_handler);
2369 _Py_IDENTIFIER(task);
2370 _Py_IDENTIFIER(message);
2371 _Py_IDENTIFIER(source_traceback);
2372
Serhiy Storchakabca49392017-09-03 08:10:14 +03002373 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002374 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002375 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002376 PyObject *error_type, *error_value, *error_traceback;
2377
2378 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2379 goto done;
2380 }
2381
2382 /* Save the current exception, if any. */
2383 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2384
2385 context = PyDict_New();
2386 if (context == NULL) {
2387 goto finally;
2388 }
2389
2390 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2391 if (message == NULL) {
2392 goto finally;
2393 }
2394
2395 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2396 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2397 {
2398 goto finally;
2399 }
2400
2401 if (task->task_source_tb != NULL) {
2402 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2403 task->task_source_tb) < 0)
2404 {
2405 goto finally;
2406 }
2407 }
2408
2409 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2410 if (func != NULL) {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002411 PyObject *res = _PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002412 if (res == NULL) {
2413 PyErr_WriteUnraisable(func);
2414 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002415 else {
2416 Py_DECREF(res);
2417 }
2418 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002419 }
2420
2421finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002422 Py_XDECREF(context);
2423 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002424
2425 /* Restore the saved exception. */
2426 PyErr_Restore(error_type, error_value, error_traceback);
2427
2428done:
2429 FutureObj_finalize((FutureObj*)task);
2430}
2431
2432static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2433
2434static PyMethodDef TaskType_methods[] = {
2435 _ASYNCIO_FUTURE_RESULT_METHODDEF
2436 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002437 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2438 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2439 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2440 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002441 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2442 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002443 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2444 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2445 _ASYNCIO_TASK_CANCEL_METHODDEF
2446 _ASYNCIO_TASK_GET_STACK_METHODDEF
2447 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002448 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002449 _ASYNCIO_TASK_GET_NAME_METHODDEF
2450 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002451 _ASYNCIO_TASK_GET_CORO_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002452 {NULL, NULL} /* Sentinel */
2453};
2454
2455static PyGetSetDef TaskType_getsetlist[] = {
2456 FUTURE_COMMON_GETSETLIST
2457 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2458 (setter)TaskObj_set_log_destroy_pending, NULL},
2459 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2460 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2461 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2462 {NULL} /* Sentinel */
2463};
2464
2465static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002466 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002467 "_asyncio.Task",
2468 sizeof(TaskObj), /* tp_basicsize */
2469 .tp_base = &FutureType,
2470 .tp_dealloc = TaskObj_dealloc,
2471 .tp_as_async = &FutureType_as_async,
2472 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002473 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002474 .tp_doc = _asyncio_Task___init____doc__,
2475 .tp_traverse = (traverseproc)TaskObj_traverse,
2476 .tp_clear = (inquiry)TaskObj_clear,
2477 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2478 .tp_iter = (getiterfunc)future_new_iter,
2479 .tp_methods = TaskType_methods,
2480 .tp_getset = TaskType_getsetlist,
2481 .tp_dictoffset = offsetof(TaskObj, dict),
2482 .tp_init = (initproc)_asyncio_Task___init__,
2483 .tp_new = PyType_GenericNew,
2484 .tp_finalize = (destructor)TaskObj_finalize,
2485};
2486
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002487static void
2488TaskObj_dealloc(PyObject *self)
2489{
2490 TaskObj *task = (TaskObj *)self;
2491
2492 if (Task_CheckExact(self)) {
2493 /* When fut is subclass of Task, finalizer is called from
2494 * subtype_dealloc.
2495 */
2496 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2497 // resurrected.
2498 return;
2499 }
2500 }
2501
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002502 PyObject_GC_UnTrack(self);
2503
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002504 if (task->task_weakreflist != NULL) {
2505 PyObject_ClearWeakRefs(self);
2506 }
2507
2508 (void)TaskObj_clear(task);
2509 Py_TYPE(task)->tp_free(task);
2510}
2511
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002512static int
2513task_call_step_soon(TaskObj *task, PyObject *arg)
2514{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002515 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002516 if (cb == NULL) {
2517 return -1;
2518 }
2519
Yury Selivanovf23746a2018-01-22 19:11:18 -05002520 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002521 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002522 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002523}
2524
2525static PyObject *
2526task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2527{
2528 PyObject* msg;
2529
2530 va_list vargs;
2531#ifdef HAVE_STDARG_PROTOTYPES
2532 va_start(vargs, format);
2533#else
2534 va_start(vargs);
2535#endif
2536 msg = PyUnicode_FromFormatV(format, vargs);
2537 va_end(vargs);
2538
2539 if (msg == NULL) {
2540 return NULL;
2541 }
2542
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002543 PyObject *e = _PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002544 Py_DECREF(msg);
2545 if (e == NULL) {
2546 return NULL;
2547 }
2548
2549 if (task_call_step_soon(task, e) == -1) {
2550 Py_DECREF(e);
2551 return NULL;
2552 }
2553
2554 Py_DECREF(e);
2555 Py_RETURN_NONE;
2556}
2557
2558static PyObject *
2559task_step_impl(TaskObj *task, PyObject *exc)
2560{
2561 int res;
2562 int clear_exc = 0;
2563 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002564 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002565 PyObject *o;
2566
2567 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002568 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002569 "_step(): already done: %R %R",
2570 task,
2571 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002572 goto fail;
2573 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002574
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002575 if (task->task_must_cancel) {
2576 assert(exc != Py_None);
2577
2578 if (exc) {
2579 /* Check if exc is a CancelledError */
2580 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2581 if (res == -1) {
2582 /* An error occurred, abort */
2583 goto fail;
2584 }
2585 if (res == 0) {
2586 /* exc is not CancelledError; reset it to NULL */
2587 exc = NULL;
2588 }
2589 }
2590
2591 if (!exc) {
2592 /* exc was not a CancelledError */
Victor Stinner2ff58a22019-06-17 14:27:23 +02002593 exc = PyObject_CallNoArgs(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002594 if (!exc) {
2595 goto fail;
2596 }
2597 clear_exc = 1;
2598 }
2599
2600 task->task_must_cancel = 0;
2601 }
2602
2603 Py_CLEAR(task->task_fut_waiter);
2604
Serhiy Storchakabca49392017-09-03 08:10:14 +03002605 coro = task->task_coro;
2606 if (coro == NULL) {
2607 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2608 return NULL;
2609 }
2610
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002611 if (exc == NULL) {
2612 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2613 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2614 }
2615 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002616 result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002617 }
2618 }
2619 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002620 result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002621 if (clear_exc) {
2622 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002623 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002624 }
2625 }
2626
2627 if (result == NULL) {
2628 PyObject *et, *ev, *tb;
2629
2630 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2631 /* The error is StopIteration and that means that
2632 the underlying coroutine has resolved */
Yury Selivanovedad4d82019-09-25 03:32:08 -07002633
2634 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002635 if (task->task_must_cancel) {
2636 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002637 task->task_must_cancel = 0;
Yury Selivanovedad4d82019-09-25 03:32:08 -07002638 res = future_cancel((FutureObj*)task);
INADA Naoki991adca2017-05-11 21:18:38 +09002639 }
Yury Selivanovedad4d82019-09-25 03:32:08 -07002640 else {
2641 res = future_set_result((FutureObj*)task, o);
2642 }
2643
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002644 Py_DECREF(o);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002645
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002646 if (res == NULL) {
2647 return NULL;
2648 }
2649 Py_DECREF(res);
2650 Py_RETURN_NONE;
2651 }
2652
2653 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2654 /* CancelledError */
2655 PyErr_Clear();
2656 return future_cancel((FutureObj*)task);
2657 }
2658
2659 /* Some other exception; pop it and call Task.set_exception() */
2660 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002661
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002662 assert(et);
2663 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2664 PyErr_NormalizeException(&et, &ev, &tb);
2665 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002666 if (tb != NULL) {
2667 PyException_SetTraceback(ev, tb);
2668 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002669 o = future_set_exception((FutureObj*)task, ev);
2670 if (!o) {
2671 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002672 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002673 Py_XDECREF(tb);
2674 Py_XDECREF(ev);
2675 goto fail;
2676 }
2677 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002678 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002679
Yury Selivanov431b5402019-05-27 14:45:12 +02002680 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2681 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2682 {
2683 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002684 PyErr_Restore(et, ev, tb);
2685 goto fail;
2686 }
2687
Serhiy Storchakabca49392017-09-03 08:10:14 +03002688 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002689 Py_XDECREF(tb);
2690 Py_XDECREF(ev);
2691
2692 Py_RETURN_NONE;
2693 }
2694
2695 if (result == (PyObject*)task) {
2696 /* We have a task that wants to await on itself */
2697 goto self_await;
2698 }
2699
2700 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2701 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2702 PyObject *wrapper;
2703 PyObject *res;
2704 FutureObj *fut = (FutureObj*)result;
2705
2706 /* Check if `result` future is attached to a different loop */
2707 if (fut->fut_loop != task->task_loop) {
2708 goto different_loop;
2709 }
2710
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002711 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002712 goto yield_insteadof_yf;
2713 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002714
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002715 fut->fut_blocking = 0;
2716
2717 /* result.add_done_callback(task._wakeup) */
2718 wrapper = TaskWakeupMethWrapper_new(task);
2719 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002720 goto fail;
2721 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002722 res = future_add_done_callback(
2723 (FutureObj*)result, wrapper, task->task_context);
2724 Py_DECREF(wrapper);
2725 if (res == NULL) {
2726 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002727 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002728 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002729
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002730 /* task._fut_waiter = result */
2731 task->task_fut_waiter = result; /* no incref is necessary */
2732
2733 if (task->task_must_cancel) {
2734 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002735 int is_true;
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002736 r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002737 if (r == NULL) {
2738 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002739 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002740 is_true = PyObject_IsTrue(r);
2741 Py_DECREF(r);
2742 if (is_true < 0) {
2743 return NULL;
2744 }
2745 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002746 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002747 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002748 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002749
2750 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002751 }
2752
2753 /* Check if `result` is None */
2754 if (result == Py_None) {
2755 /* Bare yield relinquishes control for one event loop iteration. */
2756 if (task_call_step_soon(task, NULL)) {
2757 goto fail;
2758 }
2759 return result;
2760 }
2761
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002762 /* Check if `result` is a Future-compatible object */
2763 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2764 goto fail;
2765 }
2766 if (o != NULL && o != Py_None) {
2767 /* `result` is a Future-compatible object */
2768 PyObject *wrapper;
2769 PyObject *res;
2770
2771 int blocking = PyObject_IsTrue(o);
2772 Py_DECREF(o);
2773 if (blocking < 0) {
2774 goto fail;
2775 }
2776
2777 /* Check if `result` future is attached to a different loop */
2778 PyObject *oloop = get_future_loop(result);
2779 if (oloop == NULL) {
2780 goto fail;
2781 }
2782 if (oloop != task->task_loop) {
2783 Py_DECREF(oloop);
2784 goto different_loop;
2785 }
2786 Py_DECREF(oloop);
2787
2788 if (!blocking) {
2789 goto yield_insteadof_yf;
2790 }
2791
2792 /* result._asyncio_future_blocking = False */
2793 if (_PyObject_SetAttrId(
2794 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2795 goto fail;
2796 }
2797
2798 wrapper = TaskWakeupMethWrapper_new(task);
2799 if (wrapper == NULL) {
2800 goto fail;
2801 }
2802
2803 /* result.add_done_callback(task._wakeup) */
2804 PyObject *add_cb = _PyObject_GetAttrId(
2805 result, &PyId_add_done_callback);
2806 if (add_cb == NULL) {
2807 Py_DECREF(wrapper);
2808 goto fail;
2809 }
2810 PyObject *stack[2];
2811 stack[0] = wrapper;
2812 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002813 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002814 Py_DECREF(add_cb);
2815 Py_DECREF(wrapper);
2816 if (res == NULL) {
2817 goto fail;
2818 }
2819 Py_DECREF(res);
2820
2821 /* task._fut_waiter = result */
2822 task->task_fut_waiter = result; /* no incref is necessary */
2823
2824 if (task->task_must_cancel) {
2825 PyObject *r;
2826 int is_true;
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002827 r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002828 if (r == NULL) {
2829 return NULL;
2830 }
2831 is_true = PyObject_IsTrue(r);
2832 Py_DECREF(r);
2833 if (is_true < 0) {
2834 return NULL;
2835 }
2836 else if (is_true) {
2837 task->task_must_cancel = 0;
2838 }
2839 }
2840
2841 Py_RETURN_NONE;
2842 }
2843
2844 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002845 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002846 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2847 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002848 goto fail;
2849 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002850 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002851 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002852 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002853 task, PyExc_RuntimeError,
2854 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002855 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002856 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002857 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002858 }
2859
2860 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002861 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002862 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002863 Py_DECREF(result);
2864 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002865
2866self_await:
2867 o = task_set_error_soon(
2868 task, PyExc_RuntimeError,
2869 "Task cannot await on itself: %R", task);
2870 Py_DECREF(result);
2871 return o;
2872
2873yield_insteadof_yf:
2874 o = task_set_error_soon(
2875 task, PyExc_RuntimeError,
2876 "yield was used instead of yield from "
2877 "in task %R with %R",
2878 task, result);
2879 Py_DECREF(result);
2880 return o;
2881
2882different_loop:
2883 o = task_set_error_soon(
2884 task, PyExc_RuntimeError,
2885 "Task %R got Future %R attached to a different loop",
2886 task, result);
2887 Py_DECREF(result);
2888 return o;
2889
2890fail:
2891 Py_XDECREF(result);
2892 return NULL;
2893}
2894
2895static PyObject *
2896task_step(TaskObj *task, PyObject *exc)
2897{
2898 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002899
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002900 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002901 return NULL;
2902 }
2903
2904 res = task_step_impl(task, exc);
2905
2906 if (res == NULL) {
2907 PyObject *et, *ev, *tb;
2908 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002909 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002910 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002911 return NULL;
2912 }
2913 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002914 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002915 Py_DECREF(res);
2916 return NULL;
2917 }
2918 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002919 return res;
2920 }
2921 }
2922}
2923
2924static PyObject *
2925task_wakeup(TaskObj *task, PyObject *o)
2926{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002927 PyObject *et, *ev, *tb;
2928 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002929 assert(o);
2930
2931 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2932 PyObject *fut_result = NULL;
2933 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002934
2935 switch(res) {
2936 case -1:
2937 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002938 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002939 case 0:
2940 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002941 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002942 default:
2943 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002944 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002945 Py_DECREF(fut_result);
2946 return result;
2947 }
2948 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002949 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002950 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2951 if (fut_result != NULL) {
2952 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002953 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002954 }
2955 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002956 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002957
2958 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002959 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2960 PyErr_NormalizeException(&et, &ev, &tb);
2961 }
2962
Yury Selivanov22feeb82018-01-24 11:31:01 -05002963 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002964
2965 Py_DECREF(et);
2966 Py_XDECREF(tb);
2967 Py_XDECREF(ev);
2968
2969 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002970}
2971
2972
Yury Selivanova70232f2017-12-13 14:49:42 -05002973/*********************** Functions **************************/
2974
2975
2976/*[clinic input]
2977_asyncio._get_running_loop
2978
2979Return the running event loop or None.
2980
2981This is a low-level function intended to be used by event loops.
2982This function is thread-specific.
2983
2984[clinic start generated code]*/
2985
2986static PyObject *
2987_asyncio__get_running_loop_impl(PyObject *module)
2988/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
2989{
2990 PyObject *loop;
2991 if (get_running_loop(&loop)) {
2992 return NULL;
2993 }
2994 if (loop == NULL) {
2995 /* There's no currently running event loop */
2996 Py_RETURN_NONE;
2997 }
2998 return loop;
2999}
3000
3001/*[clinic input]
3002_asyncio._set_running_loop
3003 loop: 'O'
3004 /
3005
3006Set the running event loop.
3007
3008This is a low-level function intended to be used by event loops.
3009This function is thread-specific.
3010[clinic start generated code]*/
3011
3012static PyObject *
3013_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3014/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3015{
3016 if (set_running_loop(loop)) {
3017 return NULL;
3018 }
3019 Py_RETURN_NONE;
3020}
3021
3022/*[clinic input]
3023_asyncio.get_event_loop
3024
3025Return an asyncio event loop.
3026
3027When called from a coroutine or a callback (e.g. scheduled with
3028call_soon or similar API), this function will always return the
3029running event loop.
3030
3031If there is no running event loop set, the function will return
3032the result of `get_event_loop_policy().get_event_loop()` call.
3033[clinic start generated code]*/
3034
3035static PyObject *
3036_asyncio_get_event_loop_impl(PyObject *module)
3037/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3038{
3039 return get_event_loop();
3040}
3041
3042/*[clinic input]
3043_asyncio.get_running_loop
3044
3045Return the running event loop. Raise a RuntimeError if there is none.
3046
3047This function is thread-specific.
3048[clinic start generated code]*/
3049
3050static PyObject *
3051_asyncio_get_running_loop_impl(PyObject *module)
3052/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3053{
3054 PyObject *loop;
3055 if (get_running_loop(&loop)) {
3056 return NULL;
3057 }
3058 if (loop == NULL) {
3059 /* There's no currently running event loop */
3060 PyErr_SetString(
3061 PyExc_RuntimeError, "no running event loop");
3062 }
3063 return loop;
3064}
3065
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003066/*[clinic input]
3067_asyncio._register_task
3068
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003069 task: object
3070
3071Register a new task in asyncio as executed by loop.
3072
3073Returns None.
3074[clinic start generated code]*/
3075
3076static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003077_asyncio__register_task_impl(PyObject *module, PyObject *task)
3078/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003079{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003080 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003081 return NULL;
3082 }
3083 Py_RETURN_NONE;
3084}
3085
3086
3087/*[clinic input]
3088_asyncio._unregister_task
3089
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003090 task: object
3091
3092Unregister a task.
3093
3094Returns None.
3095[clinic start generated code]*/
3096
3097static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003098_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3099/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003100{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003101 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003102 return NULL;
3103 }
3104 Py_RETURN_NONE;
3105}
3106
3107
3108/*[clinic input]
3109_asyncio._enter_task
3110
3111 loop: object
3112 task: object
3113
3114Enter into task execution or resume suspended task.
3115
3116Task belongs to loop.
3117
3118Returns None.
3119[clinic start generated code]*/
3120
3121static PyObject *
3122_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3123/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3124{
3125 if (enter_task(loop, task) < 0) {
3126 return NULL;
3127 }
3128 Py_RETURN_NONE;
3129}
3130
3131
3132/*[clinic input]
3133_asyncio._leave_task
3134
3135 loop: object
3136 task: object
3137
3138Leave task execution or suspend a task.
3139
3140Task belongs to loop.
3141
3142Returns None.
3143[clinic start generated code]*/
3144
3145static PyObject *
3146_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3147/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3148{
3149 if (leave_task(loop, task) < 0) {
3150 return NULL;
3151 }
3152 Py_RETURN_NONE;
3153}
3154
Yury Selivanova70232f2017-12-13 14:49:42 -05003155
Yury Selivanov9d411c12018-01-23 15:10:03 -05003156/*********************** PyRunningLoopHolder ********************/
3157
3158
3159static PyRunningLoopHolder *
3160new_running_loop_holder(PyObject *loop)
3161{
3162 PyRunningLoopHolder *rl = PyObject_New(
3163 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3164 if (rl == NULL) {
3165 return NULL;
3166 }
3167
3168#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3169 rl->rl_pid = getpid();
3170#endif
3171
3172 Py_INCREF(loop);
3173 rl->rl_loop = loop;
3174
3175 return rl;
3176}
3177
3178
3179static void
3180PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3181{
3182 Py_CLEAR(rl->rl_loop);
3183 PyObject_Free(rl);
3184}
3185
3186
3187static PyTypeObject PyRunningLoopHolder_Type = {
3188 PyVarObject_HEAD_INIT(NULL, 0)
3189 "_RunningLoopHolder",
3190 sizeof(PyRunningLoopHolder),
3191 .tp_getattro = PyObject_GenericGetAttr,
3192 .tp_flags = Py_TPFLAGS_DEFAULT,
3193 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3194};
3195
3196
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003197/*********************** Module **************************/
3198
3199
3200static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003201module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003202{
3203 PyObject *next;
3204 PyObject *current;
3205
3206 next = (PyObject*) fi_freelist;
3207 while (next != NULL) {
3208 assert(fi_freelist_len > 0);
3209 fi_freelist_len--;
3210
3211 current = next;
3212 next = (PyObject*) ((futureiterobject*) current)->future;
3213 PyObject_GC_Del(current);
3214 }
3215 assert(fi_freelist_len == 0);
3216 fi_freelist = NULL;
3217}
3218
3219
3220static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003221module_free(void *m)
3222{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003223 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003224 Py_CLEAR(traceback_extract_stack);
3225 Py_CLEAR(asyncio_future_repr_info_func);
3226 Py_CLEAR(asyncio_get_event_loop_policy);
3227 Py_CLEAR(asyncio_iscoroutine_func);
3228 Py_CLEAR(asyncio_task_get_stack_func);
3229 Py_CLEAR(asyncio_task_print_stack_func);
3230 Py_CLEAR(asyncio_task_repr_info_func);
3231 Py_CLEAR(asyncio_InvalidStateError);
3232 Py_CLEAR(asyncio_CancelledError);
3233
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003234 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003235 Py_CLEAR(current_tasks);
3236 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003237
Yury Selivanovf23746a2018-01-22 19:11:18 -05003238 Py_CLEAR(context_kwname);
3239
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003240 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003241}
3242
3243static int
3244module_init(void)
3245{
3246 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003247
3248 asyncio_mod = PyImport_ImportModule("asyncio");
3249 if (asyncio_mod == NULL) {
3250 goto fail;
3251 }
Ben Harper321def82019-10-07 12:19:58 -04003252 if (module_initialized != 0) {
3253 return 0;
3254 }
3255 else {
3256 module_initialized = 1;
3257 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003258
3259 current_tasks = PyDict_New();
3260 if (current_tasks == NULL) {
3261 goto fail;
3262 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003263
Yury Selivanova9d7e552017-12-19 07:18:45 -05003264 iscoroutine_typecache = PySet_New(NULL);
3265 if (iscoroutine_typecache == NULL) {
3266 goto fail;
3267 }
3268
Yury Selivanovf23746a2018-01-22 19:11:18 -05003269
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003270 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003271 if (context_kwname == NULL) {
3272 goto fail;
3273 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003274
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003275#define WITH_MOD(NAME) \
3276 Py_CLEAR(module); \
3277 module = PyImport_ImportModule(NAME); \
3278 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003279 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003280 }
3281
3282#define GET_MOD_ATTR(VAR, NAME) \
3283 VAR = PyObject_GetAttrString(module, NAME); \
3284 if (VAR == NULL) { \
3285 goto fail; \
3286 }
3287
3288 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003289 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003290
3291 WITH_MOD("asyncio.base_futures")
3292 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003293
3294 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003295 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3296 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3297
3298 WITH_MOD("asyncio.base_tasks")
3299 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3300 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3301 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3302
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003303 WITH_MOD("asyncio.coroutines")
3304 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3305
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003306 WITH_MOD("traceback")
3307 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3308
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003309 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003310 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003311 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003312 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003313 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003314 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003315 goto fail;
3316 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003317
Serhiy Storchakabca49392017-09-03 08:10:14 +03003318 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003319 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003320
INADA Naokic411a7d2016-10-18 11:48:14 +09003321fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003322 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003323 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003324 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003325
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003326#undef WITH_MOD
3327#undef GET_MOD_ATTR
3328}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003329
INADA Naokic411a7d2016-10-18 11:48:14 +09003330PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003331
Yury Selivanova70232f2017-12-13 14:49:42 -05003332static PyMethodDef asyncio_methods[] = {
3333 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3334 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3335 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3336 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003337 _ASYNCIO__REGISTER_TASK_METHODDEF
3338 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3339 _ASYNCIO__ENTER_TASK_METHODDEF
3340 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003341 {NULL, NULL}
3342};
3343
INADA Naoki9f2ce252016-10-15 15:39:19 +09003344static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003345 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003346 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003347 module_doc, /* m_doc */
3348 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003349 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003350 NULL, /* m_slots */
3351 NULL, /* m_traverse */
3352 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003353 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003354};
3355
3356
3357PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003358PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003359{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003360 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003361 return NULL;
3362 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003363 if (PyType_Ready(&FutureType) < 0) {
3364 return NULL;
3365 }
3366 if (PyType_Ready(&FutureIterType) < 0) {
3367 return NULL;
3368 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003369 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003370 return NULL;
3371 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003372 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003373 return NULL;
3374 }
3375 if (PyType_Ready(&TaskType) < 0) {
3376 return NULL;
3377 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003378 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3379 return NULL;
3380 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003381
INADA Naoki9f2ce252016-10-15 15:39:19 +09003382 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003383 if (m == NULL) {
3384 return NULL;
3385 }
3386
3387 Py_INCREF(&FutureType);
3388 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3389 Py_DECREF(&FutureType);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003390 Py_DECREF(m);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003391 return NULL;
3392 }
3393
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003394 Py_INCREF(&TaskType);
3395 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3396 Py_DECREF(&TaskType);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003397 Py_DECREF(m);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003398 return NULL;
3399 }
3400
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003401 Py_INCREF(all_tasks);
3402 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3403 Py_DECREF(all_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003404 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003405 return NULL;
3406 }
3407
3408 Py_INCREF(current_tasks);
3409 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3410 Py_DECREF(current_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003411 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003412 return NULL;
3413 }
3414
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003415 return m;
3416}