blob: 70da40a8a3b86301e1ecf5d83a634242c509b5d2 [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
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001384static PyObject *
1385future_cls_getitem(PyObject *cls, PyObject *type)
1386{
1387 Py_INCREF(cls);
1388 return cls;
1389}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001390
1391static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001392 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001393 0, /* am_aiter */
1394 0 /* am_anext */
1395};
1396
1397static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001398 _ASYNCIO_FUTURE_RESULT_METHODDEF
1399 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1400 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1401 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1402 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1403 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1404 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1405 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1406 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001407 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001408 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001409 {"__class_getitem__", future_cls_getitem, METH_O|METH_CLASS, NULL},
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001410 {NULL, NULL} /* Sentinel */
1411};
1412
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001413#define FUTURE_COMMON_GETSETLIST \
1414 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1415 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1416 (setter)FutureObj_set_blocking, NULL}, \
1417 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1418 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1419 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1420 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001421 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1422 (setter)FutureObj_set_log_traceback, NULL}, \
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001423 {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001424
1425static PyGetSetDef FutureType_getsetlist[] = {
1426 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001427 {NULL} /* Sentinel */
1428};
1429
1430static void FutureObj_dealloc(PyObject *self);
1431
1432static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001433 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001434 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001435 sizeof(FutureObj), /* tp_basicsize */
1436 .tp_dealloc = FutureObj_dealloc,
1437 .tp_as_async = &FutureType_as_async,
1438 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001439 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001440 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001441 .tp_traverse = (traverseproc)FutureObj_traverse,
1442 .tp_clear = (inquiry)FutureObj_clear,
1443 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001444 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001445 .tp_methods = FutureType_methods,
1446 .tp_getset = FutureType_getsetlist,
1447 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001448 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001449 .tp_new = PyType_GenericNew,
1450 .tp_finalize = (destructor)FutureObj_finalize,
1451};
1452
1453static void
1454FutureObj_dealloc(PyObject *self)
1455{
1456 FutureObj *fut = (FutureObj *)self;
1457
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001458 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001459 /* When fut is subclass of Future, finalizer is called from
1460 * subtype_dealloc.
1461 */
1462 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1463 // resurrected.
1464 return;
1465 }
1466 }
1467
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001468 PyObject_GC_UnTrack(self);
1469
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001470 if (fut->fut_weakreflist != NULL) {
1471 PyObject_ClearWeakRefs(self);
1472 }
1473
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001474 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001475 Py_TYPE(fut)->tp_free(fut);
1476}
1477
1478
1479/*********************** Future Iterator **************************/
1480
1481typedef struct {
1482 PyObject_HEAD
1483 FutureObj *future;
1484} futureiterobject;
1485
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001486
1487#define FI_FREELIST_MAXLEN 255
1488static futureiterobject *fi_freelist = NULL;
1489static Py_ssize_t fi_freelist_len = 0;
1490
1491
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001492static void
1493FutureIter_dealloc(futureiterobject *it)
1494{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001495 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001496 Py_CLEAR(it->future);
1497
1498 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1499 fi_freelist_len++;
1500 it->future = (FutureObj*) fi_freelist;
1501 fi_freelist = it;
1502 }
1503 else {
1504 PyObject_GC_Del(it);
1505 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001506}
1507
1508static PyObject *
1509FutureIter_iternext(futureiterobject *it)
1510{
1511 PyObject *res;
1512 FutureObj *fut = it->future;
1513
1514 if (fut == NULL) {
1515 return NULL;
1516 }
1517
1518 if (fut->fut_state == STATE_PENDING) {
1519 if (!fut->fut_blocking) {
1520 fut->fut_blocking = 1;
1521 Py_INCREF(fut);
1522 return (PyObject *)fut;
1523 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001524 PyErr_SetString(PyExc_RuntimeError,
1525 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001526 return NULL;
1527 }
1528
Serhiy Storchakabca49392017-09-03 08:10:14 +03001529 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001530 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001531 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001532 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001533 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001534 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001535 }
1536
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001537 Py_DECREF(fut);
1538 return NULL;
1539}
1540
1541static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001542FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001543{
INADA Naoki74c17532016-10-25 19:00:45 +09001544 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001545 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001546 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001547 return FutureIter_iternext(self);
1548}
1549
1550static PyObject *
1551FutureIter_throw(futureiterobject *self, PyObject *args)
1552{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001553 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001554 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1555 return NULL;
1556
1557 if (val == Py_None) {
1558 val = NULL;
1559 }
1560 if (tb == Py_None) {
1561 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001562 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1563 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1564 return NULL;
1565 }
1566
1567 Py_INCREF(type);
1568 Py_XINCREF(val);
1569 Py_XINCREF(tb);
1570
1571 if (PyExceptionClass_Check(type)) {
1572 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001573 /* No need to call PyException_SetTraceback since we'll be calling
1574 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001575 } else if (PyExceptionInstance_Check(type)) {
1576 if (val) {
1577 PyErr_SetString(PyExc_TypeError,
1578 "instance exception may not have a separate value");
1579 goto fail;
1580 }
1581 val = type;
1582 type = PyExceptionInstance_Class(type);
1583 Py_INCREF(type);
1584 if (tb == NULL)
1585 tb = PyException_GetTraceback(val);
1586 } else {
1587 PyErr_SetString(PyExc_TypeError,
1588 "exceptions must be classes deriving BaseException or "
1589 "instances of such a class");
1590 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001591 }
1592
1593 Py_CLEAR(self->future);
1594
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001595 PyErr_Restore(type, val, tb);
1596
Serhiy Storchakabca49392017-09-03 08:10:14 +03001597 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001598
1599 fail:
1600 Py_DECREF(type);
1601 Py_XDECREF(val);
1602 Py_XDECREF(tb);
1603 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001604}
1605
1606static PyObject *
1607FutureIter_close(futureiterobject *self, PyObject *arg)
1608{
1609 Py_CLEAR(self->future);
1610 Py_RETURN_NONE;
1611}
1612
1613static int
1614FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1615{
1616 Py_VISIT(it->future);
1617 return 0;
1618}
1619
1620static PyMethodDef FutureIter_methods[] = {
1621 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1622 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1623 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1624 {NULL, NULL} /* Sentinel */
1625};
1626
1627static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001628 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001629 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001630 .tp_basicsize = sizeof(futureiterobject),
1631 .tp_itemsize = 0,
1632 .tp_dealloc = (destructor)FutureIter_dealloc,
1633 .tp_getattro = PyObject_GenericGetAttr,
1634 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1635 .tp_traverse = (traverseproc)FutureIter_traverse,
1636 .tp_iter = PyObject_SelfIter,
1637 .tp_iternext = (iternextfunc)FutureIter_iternext,
1638 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001639};
1640
1641static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001642future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001643{
1644 futureiterobject *it;
1645
1646 if (!PyObject_TypeCheck(fut, &FutureType)) {
1647 PyErr_BadInternalCall();
1648 return NULL;
1649 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001650
1651 ENSURE_FUTURE_ALIVE(fut)
1652
1653 if (fi_freelist_len) {
1654 fi_freelist_len--;
1655 it = fi_freelist;
1656 fi_freelist = (futureiterobject*) it->future;
1657 it->future = NULL;
1658 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001659 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001660 else {
1661 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1662 if (it == NULL) {
1663 return NULL;
1664 }
1665 }
1666
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001667 Py_INCREF(fut);
1668 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001669 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001670 return (PyObject*)it;
1671}
1672
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001673
1674/*********************** Task **************************/
1675
1676
1677/*[clinic input]
1678class _asyncio.Task "TaskObj *" "&Task_Type"
1679[clinic start generated code]*/
1680/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1681
1682static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001683static PyObject * task_wakeup(TaskObj *, PyObject *);
1684static PyObject * task_step(TaskObj *, PyObject *);
1685
1686/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001687
INADA Naokic411a7d2016-10-18 11:48:14 +09001688static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001689TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001690{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001691 Py_CLEAR(o->sw_task);
1692 Py_CLEAR(o->sw_arg);
1693 return 0;
1694}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001695
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001696static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001697TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001698{
1699 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001700 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001701 Py_TYPE(o)->tp_free(o);
1702}
1703
1704static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001705TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001706 PyObject *args, PyObject *kwds)
1707{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001708 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1709 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1710 return NULL;
1711 }
1712 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1713 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1714 return NULL;
1715 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001716 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001717}
1718
1719static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001720TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001721 visitproc visit, void *arg)
1722{
1723 Py_VISIT(o->sw_task);
1724 Py_VISIT(o->sw_arg);
1725 return 0;
1726}
1727
1728static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001729TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001730{
1731 if (o->sw_task) {
1732 Py_INCREF(o->sw_task);
1733 return (PyObject*)o->sw_task;
1734 }
1735 Py_RETURN_NONE;
1736}
1737
Serhiy Storchakabca49392017-09-03 08:10:14 +03001738static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1739 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001740 {NULL} /* Sentinel */
1741};
1742
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001743static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001744 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001745 "TaskStepMethWrapper",
1746 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001747 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001748 .tp_getset = TaskStepMethWrapper_getsetlist,
1749 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1750 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001751 .tp_getattro = PyObject_GenericGetAttr,
1752 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001753 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1754 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001755};
1756
1757static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001758TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001759{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001760 TaskStepMethWrapper *o;
1761 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001762 if (o == NULL) {
1763 return NULL;
1764 }
1765
1766 Py_INCREF(task);
1767 o->sw_task = task;
1768
1769 Py_XINCREF(arg);
1770 o->sw_arg = arg;
1771
1772 PyObject_GC_Track(o);
1773 return (PyObject*) o;
1774}
1775
1776/* ----- Task._wakeup wrapper */
1777
1778static PyObject *
1779TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1780 PyObject *args, PyObject *kwds)
1781{
1782 PyObject *fut;
1783
Serhiy Storchakabca49392017-09-03 08:10:14 +03001784 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1785 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1786 return NULL;
1787 }
1788 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001789 return NULL;
1790 }
1791
Yury Selivanov22feeb82018-01-24 11:31:01 -05001792 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001793}
1794
1795static int
1796TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1797{
1798 Py_CLEAR(o->ww_task);
1799 return 0;
1800}
1801
1802static int
1803TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1804 visitproc visit, void *arg)
1805{
1806 Py_VISIT(o->ww_task);
1807 return 0;
1808}
1809
1810static void
1811TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1812{
1813 PyObject_GC_UnTrack(o);
1814 (void)TaskWakeupMethWrapper_clear(o);
1815 Py_TYPE(o)->tp_free(o);
1816}
1817
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001818static PyObject *
1819TaskWakeupMethWrapper_get___self__(TaskWakeupMethWrapper *o, void *Py_UNUSED(ignored))
1820{
1821 if (o->ww_task) {
1822 Py_INCREF(o->ww_task);
1823 return (PyObject*)o->ww_task;
1824 }
1825 Py_RETURN_NONE;
1826}
1827
1828static PyGetSetDef TaskWakeupMethWrapper_getsetlist[] = {
1829 {"__self__", (getter)TaskWakeupMethWrapper_get___self__, NULL, NULL},
1830 {NULL} /* Sentinel */
1831};
1832
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001833static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001834 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001835 "TaskWakeupMethWrapper",
1836 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1837 .tp_itemsize = 0,
1838 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1839 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1840 .tp_getattro = PyObject_GenericGetAttr,
1841 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1842 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1843 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001844 .tp_getset = TaskWakeupMethWrapper_getsetlist,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001845};
1846
1847static PyObject *
1848TaskWakeupMethWrapper_new(TaskObj *task)
1849{
1850 TaskWakeupMethWrapper *o;
1851 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1852 if (o == NULL) {
1853 return NULL;
1854 }
1855
1856 Py_INCREF(task);
1857 o->ww_task = task;
1858
1859 PyObject_GC_Track(o);
1860 return (PyObject*) o;
1861}
1862
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001863/* ----- Task introspection helpers */
1864
1865static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001866register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001867{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001868 _Py_IDENTIFIER(add);
1869
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001870 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1871 &PyId_add, task);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001872 if (res == NULL) {
1873 return -1;
1874 }
1875 Py_DECREF(res);
1876 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001877}
1878
1879
1880static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001881unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001882{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001883 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001884
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001885 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1886 &PyId_discard, task);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001887 if (res == NULL) {
1888 return -1;
1889 }
1890 Py_DECREF(res);
1891 return 0;
1892}
1893
1894
1895static int
1896enter_task(PyObject *loop, PyObject *task)
1897{
1898 PyObject *item;
1899 Py_hash_t hash;
1900 hash = PyObject_Hash(loop);
1901 if (hash == -1) {
1902 return -1;
1903 }
1904 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1905 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001906 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001907 PyErr_Format(
1908 PyExc_RuntimeError,
1909 "Cannot enter into task %R while another " \
1910 "task %R is being executed.",
1911 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001912 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001913 return -1;
1914 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001915 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001916 return -1;
1917 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001918 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001919}
1920
1921
1922static int
1923leave_task(PyObject *loop, PyObject *task)
1924/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1925{
1926 PyObject *item;
1927 Py_hash_t hash;
1928 hash = PyObject_Hash(loop);
1929 if (hash == -1) {
1930 return -1;
1931 }
1932 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1933 if (item != task) {
1934 if (item == NULL) {
1935 /* Not entered, replace with None */
1936 item = Py_None;
1937 }
1938 PyErr_Format(
1939 PyExc_RuntimeError,
1940 "Leaving task %R does not match the current task %R.",
1941 task, item, NULL);
1942 return -1;
1943 }
1944 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1945}
1946
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001947/* ----- Task */
1948
1949/*[clinic input]
1950_asyncio.Task.__init__
1951
Serhiy Storchakabca49392017-09-03 08:10:14 +03001952 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001953 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001954 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001955 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001956
1957A coroutine wrapped in a Future.
1958[clinic start generated code]*/
1959
1960static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001961_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
1962 PyObject *name)
1963/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001964{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001965 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09001966 return -1;
1967 }
INADA Naokic411a7d2016-10-18 11:48:14 +09001968
Yury Selivanova9d7e552017-12-19 07:18:45 -05001969 int is_coro = is_coroutine(coro);
1970 if (is_coro == -1) {
1971 return -1;
1972 }
1973 if (is_coro == 0) {
1974 self->task_log_destroy_pending = 0;
1975 PyErr_Format(PyExc_TypeError,
1976 "a coroutine was expected, got %R",
1977 coro, NULL);
1978 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02001979 }
1980
Oren Milmand019bc82018-02-13 12:28:33 +02001981 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05001982 if (self->task_context == NULL) {
1983 return -1;
1984 }
1985
Oren Milmand019bc82018-02-13 12:28:33 +02001986 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001987 self->task_must_cancel = 0;
1988 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001989 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02001990 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001991
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001992 if (name == Py_None) {
1993 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03001994 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03001995 name = PyObject_Str(name);
1996 } else {
1997 Py_INCREF(name);
1998 }
1999 Py_XSETREF(self->task_name, name);
2000 if (self->task_name == NULL) {
2001 return -1;
2002 }
2003
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002004 if (task_call_step_soon(self, NULL)) {
2005 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09002006 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002007 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002008}
2009
2010static int
2011TaskObj_clear(TaskObj *task)
2012{
2013 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002014 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002015 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002016 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002017 Py_CLEAR(task->task_fut_waiter);
2018 return 0;
2019}
2020
2021static int
2022TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2023{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002024 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002025 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002026 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002027 Py_VISIT(task->task_fut_waiter);
2028 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2029 return 0;
2030}
2031
2032static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002033TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002034{
2035 if (task->task_log_destroy_pending) {
2036 Py_RETURN_TRUE;
2037 }
2038 else {
2039 Py_RETURN_FALSE;
2040 }
2041}
2042
2043static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002044TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002045{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002046 if (val == NULL) {
2047 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2048 return -1;
2049 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002050 int is_true = PyObject_IsTrue(val);
2051 if (is_true < 0) {
2052 return -1;
2053 }
2054 task->task_log_destroy_pending = is_true;
2055 return 0;
2056}
2057
2058static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002059TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002060{
2061 if (task->task_must_cancel) {
2062 Py_RETURN_TRUE;
2063 }
2064 else {
2065 Py_RETURN_FALSE;
2066 }
2067}
2068
2069static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002070TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002071{
2072 if (task->task_coro) {
2073 Py_INCREF(task->task_coro);
2074 return task->task_coro;
2075 }
2076
2077 Py_RETURN_NONE;
2078}
2079
2080static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002081TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002082{
2083 if (task->task_fut_waiter) {
2084 Py_INCREF(task->task_fut_waiter);
2085 return task->task_fut_waiter;
2086 }
2087
2088 Py_RETURN_NONE;
2089}
2090
2091/*[clinic input]
2092@classmethod
2093_asyncio.Task.current_task
2094
Serhiy Storchakabca49392017-09-03 08:10:14 +03002095 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002096
2097Return the currently running task in an event loop or None.
2098
2099By default the current task for the current event loop is returned.
2100
2101None is returned when called not in the context of a Task.
2102[clinic start generated code]*/
2103
2104static PyObject *
2105_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002106/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002107{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002108 PyObject *ret;
2109 PyObject *current_task_func;
2110
Inada Naokic5c6cda2019-03-22 20:07:32 +09002111 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002112 "Task.current_task() is deprecated, " \
2113 "use asyncio.current_task() instead",
2114 1) < 0) {
2115 return NULL;
2116 }
2117
2118 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2119 if (current_task_func == NULL) {
2120 return NULL;
2121 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002122
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002123 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002124 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002125 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002126 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002127 return NULL;
2128 }
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002129 ret = _PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002130 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002131 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002132 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002133 }
2134 else {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002135 ret = _PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002136 Py_DECREF(current_task_func);
2137 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002138 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002139}
2140
2141/*[clinic input]
2142@classmethod
2143_asyncio.Task.all_tasks
2144
Serhiy Storchakabca49392017-09-03 08:10:14 +03002145 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002146
2147Return a set of all tasks for an event loop.
2148
2149By default all tasks for the current event loop are returned.
2150[clinic start generated code]*/
2151
2152static PyObject *
2153_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002154/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002155{
2156 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002157 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002158
Inada Naokic5c6cda2019-03-22 20:07:32 +09002159 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002160 "Task.all_tasks() is deprecated, " \
2161 "use asyncio.all_tasks() instead",
2162 1) < 0) {
2163 return NULL;
2164 }
2165
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002166 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002167 if (all_tasks_func == NULL) {
2168 return NULL;
2169 }
2170
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002171 res = _PyObject_CallOneArg(all_tasks_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002172 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002173 return res;
2174}
2175
2176/*[clinic input]
2177_asyncio.Task._repr_info
2178[clinic start generated code]*/
2179
2180static PyObject *
2181_asyncio_Task__repr_info_impl(TaskObj *self)
2182/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2183{
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002184 return _PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002185}
2186
2187/*[clinic input]
2188_asyncio.Task.cancel
2189
2190Request that this task cancel itself.
2191
2192This arranges for a CancelledError to be thrown into the
2193wrapped coroutine on the next cycle through the event loop.
2194The coroutine then has a chance to clean up or even deny
2195the request using try/except/finally.
2196
2197Unlike Future.cancel, this does not guarantee that the
2198task will be cancelled: the exception might be caught and
2199acted upon, delaying cancellation of the task or preventing
2200cancellation completely. The task may also return a value or
2201raise a different exception.
2202
2203Immediately after this method is called, Task.cancelled() will
2204not return True (unless the task was already cancelled). A
2205task will be marked as cancelled when the wrapped coroutine
2206terminates with a CancelledError exception (even if cancel()
2207was not called).
2208[clinic start generated code]*/
2209
2210static PyObject *
2211_asyncio_Task_cancel_impl(TaskObj *self)
2212/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
2213{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002214 self->task_log_tb = 0;
2215
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002216 if (self->task_state != STATE_PENDING) {
2217 Py_RETURN_FALSE;
2218 }
2219
2220 if (self->task_fut_waiter) {
2221 PyObject *res;
2222 int is_true;
2223
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002224 res = _PyObject_CallMethodIdNoArgs(self->task_fut_waiter, &PyId_cancel);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002225 if (res == NULL) {
2226 return NULL;
2227 }
2228
2229 is_true = PyObject_IsTrue(res);
2230 Py_DECREF(res);
2231 if (is_true < 0) {
2232 return NULL;
2233 }
2234
2235 if (is_true) {
2236 Py_RETURN_TRUE;
2237 }
2238 }
2239
2240 self->task_must_cancel = 1;
2241 Py_RETURN_TRUE;
2242}
2243
2244/*[clinic input]
2245_asyncio.Task.get_stack
2246
2247 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002248 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002249
2250Return the list of stack frames for this task's coroutine.
2251
2252If the coroutine is not done, this returns the stack where it is
2253suspended. If the coroutine has completed successfully or was
2254cancelled, this returns an empty list. If the coroutine was
2255terminated by an exception, this returns the list of traceback
2256frames.
2257
2258The frames are always ordered from oldest to newest.
2259
2260The optional limit gives the maximum number of frames to
2261return; by default all available frames are returned. Its
2262meaning differs depending on whether a stack or a traceback is
2263returned: the newest frames of a stack are returned, but the
2264oldest frames of a traceback are returned. (This matches the
2265behavior of the traceback module.)
2266
2267For reasons beyond our control, only one stack frame is
2268returned for a suspended coroutine.
2269[clinic start generated code]*/
2270
2271static PyObject *
2272_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002273/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002274{
2275 return PyObject_CallFunctionObjArgs(
2276 asyncio_task_get_stack_func, self, limit, NULL);
2277}
2278
2279/*[clinic input]
2280_asyncio.Task.print_stack
2281
2282 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002283 limit: object = None
2284 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002285
2286Print the stack or traceback for this task's coroutine.
2287
2288This produces output similar to that of the traceback module,
2289for the frames retrieved by get_stack(). The limit argument
2290is passed to get_stack(). The file argument is an I/O stream
2291to which the output is written; by default output is written
2292to sys.stderr.
2293[clinic start generated code]*/
2294
2295static PyObject *
2296_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2297 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002298/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002299{
2300 return PyObject_CallFunctionObjArgs(
2301 asyncio_task_print_stack_func, self, limit, file, NULL);
2302}
2303
2304/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002305_asyncio.Task.set_result
2306
2307 result: object
2308 /
2309[clinic start generated code]*/
2310
2311static PyObject *
2312_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2313/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2314{
2315 PyErr_SetString(PyExc_RuntimeError,
2316 "Task does not support set_result operation");
2317 return NULL;
2318}
2319
2320/*[clinic input]
2321_asyncio.Task.set_exception
2322
2323 exception: object
2324 /
2325[clinic start generated code]*/
2326
2327static PyObject *
2328_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2329/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2330{
2331 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002332 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002333 return NULL;
2334}
2335
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002336/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002337_asyncio.Task.get_coro
2338[clinic start generated code]*/
2339
2340static PyObject *
2341_asyncio_Task_get_coro_impl(TaskObj *self)
2342/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2343{
2344 Py_INCREF(self->task_coro);
2345 return self->task_coro;
2346}
2347
2348/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002349_asyncio.Task.get_name
2350[clinic start generated code]*/
2351
2352static PyObject *
2353_asyncio_Task_get_name_impl(TaskObj *self)
2354/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2355{
2356 if (self->task_name) {
2357 Py_INCREF(self->task_name);
2358 return self->task_name;
2359 }
2360
2361 Py_RETURN_NONE;
2362}
2363
2364/*[clinic input]
2365_asyncio.Task.set_name
2366
2367 value: object
2368 /
2369[clinic start generated code]*/
2370
2371static PyObject *
2372_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2373/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2374{
Alex Grönholma7548232018-08-09 23:49:49 +03002375 if (!PyUnicode_CheckExact(value)) {
2376 value = PyObject_Str(value);
2377 if (value == NULL) {
2378 return NULL;
2379 }
2380 } else {
2381 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002382 }
2383
Alex Grönholma7548232018-08-09 23:49:49 +03002384 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002385 Py_RETURN_NONE;
2386}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002387
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002388static void
2389TaskObj_finalize(TaskObj *task)
2390{
2391 _Py_IDENTIFIER(call_exception_handler);
2392 _Py_IDENTIFIER(task);
2393 _Py_IDENTIFIER(message);
2394 _Py_IDENTIFIER(source_traceback);
2395
Serhiy Storchakabca49392017-09-03 08:10:14 +03002396 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002397 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002398 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002399 PyObject *error_type, *error_value, *error_traceback;
2400
2401 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2402 goto done;
2403 }
2404
2405 /* Save the current exception, if any. */
2406 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2407
2408 context = PyDict_New();
2409 if (context == NULL) {
2410 goto finally;
2411 }
2412
2413 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2414 if (message == NULL) {
2415 goto finally;
2416 }
2417
2418 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2419 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2420 {
2421 goto finally;
2422 }
2423
2424 if (task->task_source_tb != NULL) {
2425 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2426 task->task_source_tb) < 0)
2427 {
2428 goto finally;
2429 }
2430 }
2431
2432 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2433 if (func != NULL) {
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002434 PyObject *res = _PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002435 if (res == NULL) {
2436 PyErr_WriteUnraisable(func);
2437 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002438 else {
2439 Py_DECREF(res);
2440 }
2441 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002442 }
2443
2444finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002445 Py_XDECREF(context);
2446 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002447
2448 /* Restore the saved exception. */
2449 PyErr_Restore(error_type, error_value, error_traceback);
2450
2451done:
2452 FutureObj_finalize((FutureObj*)task);
2453}
2454
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002455static PyObject *
2456task_cls_getitem(PyObject *cls, PyObject *type)
2457{
2458 Py_INCREF(cls);
2459 return cls;
2460}
2461
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002462static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2463
2464static PyMethodDef TaskType_methods[] = {
2465 _ASYNCIO_FUTURE_RESULT_METHODDEF
2466 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002467 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2468 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2469 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2470 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002471 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2472 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002473 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2474 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2475 _ASYNCIO_TASK_CANCEL_METHODDEF
2476 _ASYNCIO_TASK_GET_STACK_METHODDEF
2477 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002478 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002479 _ASYNCIO_TASK_GET_NAME_METHODDEF
2480 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002481 _ASYNCIO_TASK_GET_CORO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002482 {"__class_getitem__", task_cls_getitem, METH_O|METH_CLASS, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002483 {NULL, NULL} /* Sentinel */
2484};
2485
2486static PyGetSetDef TaskType_getsetlist[] = {
2487 FUTURE_COMMON_GETSETLIST
2488 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2489 (setter)TaskObj_set_log_destroy_pending, NULL},
2490 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2491 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2492 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2493 {NULL} /* Sentinel */
2494};
2495
2496static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002497 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002498 "_asyncio.Task",
2499 sizeof(TaskObj), /* tp_basicsize */
2500 .tp_base = &FutureType,
2501 .tp_dealloc = TaskObj_dealloc,
2502 .tp_as_async = &FutureType_as_async,
2503 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002504 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002505 .tp_doc = _asyncio_Task___init____doc__,
2506 .tp_traverse = (traverseproc)TaskObj_traverse,
2507 .tp_clear = (inquiry)TaskObj_clear,
2508 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2509 .tp_iter = (getiterfunc)future_new_iter,
2510 .tp_methods = TaskType_methods,
2511 .tp_getset = TaskType_getsetlist,
2512 .tp_dictoffset = offsetof(TaskObj, dict),
2513 .tp_init = (initproc)_asyncio_Task___init__,
2514 .tp_new = PyType_GenericNew,
2515 .tp_finalize = (destructor)TaskObj_finalize,
2516};
2517
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002518static void
2519TaskObj_dealloc(PyObject *self)
2520{
2521 TaskObj *task = (TaskObj *)self;
2522
2523 if (Task_CheckExact(self)) {
2524 /* When fut is subclass of Task, finalizer is called from
2525 * subtype_dealloc.
2526 */
2527 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2528 // resurrected.
2529 return;
2530 }
2531 }
2532
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002533 PyObject_GC_UnTrack(self);
2534
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002535 if (task->task_weakreflist != NULL) {
2536 PyObject_ClearWeakRefs(self);
2537 }
2538
2539 (void)TaskObj_clear(task);
2540 Py_TYPE(task)->tp_free(task);
2541}
2542
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002543static int
2544task_call_step_soon(TaskObj *task, PyObject *arg)
2545{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002546 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002547 if (cb == NULL) {
2548 return -1;
2549 }
2550
Yury Selivanovf23746a2018-01-22 19:11:18 -05002551 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002552 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002553 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002554}
2555
2556static PyObject *
2557task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2558{
2559 PyObject* msg;
2560
2561 va_list vargs;
2562#ifdef HAVE_STDARG_PROTOTYPES
2563 va_start(vargs, format);
2564#else
2565 va_start(vargs);
2566#endif
2567 msg = PyUnicode_FromFormatV(format, vargs);
2568 va_end(vargs);
2569
2570 if (msg == NULL) {
2571 return NULL;
2572 }
2573
Jeroen Demeyer196a5302019-07-04 12:31:34 +02002574 PyObject *e = _PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002575 Py_DECREF(msg);
2576 if (e == NULL) {
2577 return NULL;
2578 }
2579
2580 if (task_call_step_soon(task, e) == -1) {
2581 Py_DECREF(e);
2582 return NULL;
2583 }
2584
2585 Py_DECREF(e);
2586 Py_RETURN_NONE;
2587}
2588
2589static PyObject *
2590task_step_impl(TaskObj *task, PyObject *exc)
2591{
2592 int res;
2593 int clear_exc = 0;
2594 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002595 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002596 PyObject *o;
2597
2598 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002599 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002600 "_step(): already done: %R %R",
2601 task,
2602 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002603 goto fail;
2604 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002605
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002606 if (task->task_must_cancel) {
2607 assert(exc != Py_None);
2608
2609 if (exc) {
2610 /* Check if exc is a CancelledError */
2611 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2612 if (res == -1) {
2613 /* An error occurred, abort */
2614 goto fail;
2615 }
2616 if (res == 0) {
2617 /* exc is not CancelledError; reset it to NULL */
2618 exc = NULL;
2619 }
2620 }
2621
2622 if (!exc) {
2623 /* exc was not a CancelledError */
Victor Stinner2ff58a22019-06-17 14:27:23 +02002624 exc = PyObject_CallNoArgs(asyncio_CancelledError);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002625 if (!exc) {
2626 goto fail;
2627 }
2628 clear_exc = 1;
2629 }
2630
2631 task->task_must_cancel = 0;
2632 }
2633
2634 Py_CLEAR(task->task_fut_waiter);
2635
Serhiy Storchakabca49392017-09-03 08:10:14 +03002636 coro = task->task_coro;
2637 if (coro == NULL) {
2638 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
2639 return NULL;
2640 }
2641
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002642 if (exc == NULL) {
2643 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2644 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2645 }
2646 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002647 result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002648 }
2649 }
2650 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002651 result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002652 if (clear_exc) {
2653 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002654 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002655 }
2656 }
2657
2658 if (result == NULL) {
2659 PyObject *et, *ev, *tb;
2660
2661 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2662 /* The error is StopIteration and that means that
2663 the underlying coroutine has resolved */
Yury Selivanovedad4d82019-09-25 03:32:08 -07002664
2665 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002666 if (task->task_must_cancel) {
2667 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002668 task->task_must_cancel = 0;
Yury Selivanovedad4d82019-09-25 03:32:08 -07002669 res = future_cancel((FutureObj*)task);
INADA Naoki991adca2017-05-11 21:18:38 +09002670 }
Yury Selivanovedad4d82019-09-25 03:32:08 -07002671 else {
2672 res = future_set_result((FutureObj*)task, o);
2673 }
2674
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002675 Py_DECREF(o);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002676
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002677 if (res == NULL) {
2678 return NULL;
2679 }
2680 Py_DECREF(res);
2681 Py_RETURN_NONE;
2682 }
2683
2684 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2685 /* CancelledError */
2686 PyErr_Clear();
2687 return future_cancel((FutureObj*)task);
2688 }
2689
2690 /* Some other exception; pop it and call Task.set_exception() */
2691 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002692
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002693 assert(et);
2694 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2695 PyErr_NormalizeException(&et, &ev, &tb);
2696 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002697 if (tb != NULL) {
2698 PyException_SetTraceback(ev, tb);
2699 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002700 o = future_set_exception((FutureObj*)task, ev);
2701 if (!o) {
2702 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002703 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002704 Py_XDECREF(tb);
2705 Py_XDECREF(ev);
2706 goto fail;
2707 }
2708 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002709 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002710
Yury Selivanov431b5402019-05-27 14:45:12 +02002711 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2712 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2713 {
2714 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002715 PyErr_Restore(et, ev, tb);
2716 goto fail;
2717 }
2718
Serhiy Storchakabca49392017-09-03 08:10:14 +03002719 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002720 Py_XDECREF(tb);
2721 Py_XDECREF(ev);
2722
2723 Py_RETURN_NONE;
2724 }
2725
2726 if (result == (PyObject*)task) {
2727 /* We have a task that wants to await on itself */
2728 goto self_await;
2729 }
2730
2731 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2732 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2733 PyObject *wrapper;
2734 PyObject *res;
2735 FutureObj *fut = (FutureObj*)result;
2736
2737 /* Check if `result` future is attached to a different loop */
2738 if (fut->fut_loop != task->task_loop) {
2739 goto different_loop;
2740 }
2741
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002742 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002743 goto yield_insteadof_yf;
2744 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002745
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002746 fut->fut_blocking = 0;
2747
2748 /* result.add_done_callback(task._wakeup) */
2749 wrapper = TaskWakeupMethWrapper_new(task);
2750 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002751 goto fail;
2752 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002753 res = future_add_done_callback(
2754 (FutureObj*)result, wrapper, task->task_context);
2755 Py_DECREF(wrapper);
2756 if (res == NULL) {
2757 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002758 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002759 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002760
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002761 /* task._fut_waiter = result */
2762 task->task_fut_waiter = result; /* no incref is necessary */
2763
2764 if (task->task_must_cancel) {
2765 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002766 int is_true;
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002767 r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002768 if (r == NULL) {
2769 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002770 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002771 is_true = PyObject_IsTrue(r);
2772 Py_DECREF(r);
2773 if (is_true < 0) {
2774 return NULL;
2775 }
2776 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002777 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002778 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002779 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002780
2781 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002782 }
2783
2784 /* Check if `result` is None */
2785 if (result == Py_None) {
2786 /* Bare yield relinquishes control for one event loop iteration. */
2787 if (task_call_step_soon(task, NULL)) {
2788 goto fail;
2789 }
2790 return result;
2791 }
2792
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002793 /* Check if `result` is a Future-compatible object */
2794 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2795 goto fail;
2796 }
2797 if (o != NULL && o != Py_None) {
2798 /* `result` is a Future-compatible object */
2799 PyObject *wrapper;
2800 PyObject *res;
2801
2802 int blocking = PyObject_IsTrue(o);
2803 Py_DECREF(o);
2804 if (blocking < 0) {
2805 goto fail;
2806 }
2807
2808 /* Check if `result` future is attached to a different loop */
2809 PyObject *oloop = get_future_loop(result);
2810 if (oloop == NULL) {
2811 goto fail;
2812 }
2813 if (oloop != task->task_loop) {
2814 Py_DECREF(oloop);
2815 goto different_loop;
2816 }
2817 Py_DECREF(oloop);
2818
2819 if (!blocking) {
2820 goto yield_insteadof_yf;
2821 }
2822
2823 /* result._asyncio_future_blocking = False */
2824 if (_PyObject_SetAttrId(
2825 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2826 goto fail;
2827 }
2828
2829 wrapper = TaskWakeupMethWrapper_new(task);
2830 if (wrapper == NULL) {
2831 goto fail;
2832 }
2833
2834 /* result.add_done_callback(task._wakeup) */
2835 PyObject *add_cb = _PyObject_GetAttrId(
2836 result, &PyId_add_done_callback);
2837 if (add_cb == NULL) {
2838 Py_DECREF(wrapper);
2839 goto fail;
2840 }
2841 PyObject *stack[2];
2842 stack[0] = wrapper;
2843 stack[1] = (PyObject *)task->task_context;
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +02002844 res = _PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002845 Py_DECREF(add_cb);
2846 Py_DECREF(wrapper);
2847 if (res == NULL) {
2848 goto fail;
2849 }
2850 Py_DECREF(res);
2851
2852 /* task._fut_waiter = result */
2853 task->task_fut_waiter = result; /* no incref is necessary */
2854
2855 if (task->task_must_cancel) {
2856 PyObject *r;
2857 int is_true;
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02002858 r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002859 if (r == NULL) {
2860 return NULL;
2861 }
2862 is_true = PyObject_IsTrue(r);
2863 Py_DECREF(r);
2864 if (is_true < 0) {
2865 return NULL;
2866 }
2867 else if (is_true) {
2868 task->task_must_cancel = 0;
2869 }
2870 }
2871
2872 Py_RETURN_NONE;
2873 }
2874
2875 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002876 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002877 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2878 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002879 goto fail;
2880 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002881 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002882 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002883 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002884 task, PyExc_RuntimeError,
2885 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002886 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002887 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002888 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002889 }
2890
2891 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002892 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002893 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002894 Py_DECREF(result);
2895 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002896
2897self_await:
2898 o = task_set_error_soon(
2899 task, PyExc_RuntimeError,
2900 "Task cannot await on itself: %R", task);
2901 Py_DECREF(result);
2902 return o;
2903
2904yield_insteadof_yf:
2905 o = task_set_error_soon(
2906 task, PyExc_RuntimeError,
2907 "yield was used instead of yield from "
2908 "in task %R with %R",
2909 task, result);
2910 Py_DECREF(result);
2911 return o;
2912
2913different_loop:
2914 o = task_set_error_soon(
2915 task, PyExc_RuntimeError,
2916 "Task %R got Future %R attached to a different loop",
2917 task, result);
2918 Py_DECREF(result);
2919 return o;
2920
2921fail:
2922 Py_XDECREF(result);
2923 return NULL;
2924}
2925
2926static PyObject *
2927task_step(TaskObj *task, PyObject *exc)
2928{
2929 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002930
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002931 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002932 return NULL;
2933 }
2934
2935 res = task_step_impl(task, exc);
2936
2937 if (res == NULL) {
2938 PyObject *et, *ev, *tb;
2939 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002940 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002941 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002942 return NULL;
2943 }
2944 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002945 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002946 Py_DECREF(res);
2947 return NULL;
2948 }
2949 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002950 return res;
2951 }
2952 }
2953}
2954
2955static PyObject *
2956task_wakeup(TaskObj *task, PyObject *o)
2957{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002958 PyObject *et, *ev, *tb;
2959 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002960 assert(o);
2961
2962 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2963 PyObject *fut_result = NULL;
2964 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002965
2966 switch(res) {
2967 case -1:
2968 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002969 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002970 case 0:
2971 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002972 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002973 default:
2974 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002975 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002976 Py_DECREF(fut_result);
2977 return result;
2978 }
2979 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002980 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002981 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2982 if (fut_result != NULL) {
2983 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002984 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002985 }
2986 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002987 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002988
2989 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002990 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2991 PyErr_NormalizeException(&et, &ev, &tb);
2992 }
2993
Yury Selivanov22feeb82018-01-24 11:31:01 -05002994 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002995
2996 Py_DECREF(et);
2997 Py_XDECREF(tb);
2998 Py_XDECREF(ev);
2999
3000 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003001}
3002
3003
Yury Selivanova70232f2017-12-13 14:49:42 -05003004/*********************** Functions **************************/
3005
3006
3007/*[clinic input]
3008_asyncio._get_running_loop
3009
3010Return the running event loop or None.
3011
3012This is a low-level function intended to be used by event loops.
3013This function is thread-specific.
3014
3015[clinic start generated code]*/
3016
3017static PyObject *
3018_asyncio__get_running_loop_impl(PyObject *module)
3019/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3020{
3021 PyObject *loop;
3022 if (get_running_loop(&loop)) {
3023 return NULL;
3024 }
3025 if (loop == NULL) {
3026 /* There's no currently running event loop */
3027 Py_RETURN_NONE;
3028 }
3029 return loop;
3030}
3031
3032/*[clinic input]
3033_asyncio._set_running_loop
3034 loop: 'O'
3035 /
3036
3037Set the running event loop.
3038
3039This is a low-level function intended to be used by event loops.
3040This function is thread-specific.
3041[clinic start generated code]*/
3042
3043static PyObject *
3044_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3045/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3046{
3047 if (set_running_loop(loop)) {
3048 return NULL;
3049 }
3050 Py_RETURN_NONE;
3051}
3052
3053/*[clinic input]
3054_asyncio.get_event_loop
3055
3056Return an asyncio event loop.
3057
3058When called from a coroutine or a callback (e.g. scheduled with
3059call_soon or similar API), this function will always return the
3060running event loop.
3061
3062If there is no running event loop set, the function will return
3063the result of `get_event_loop_policy().get_event_loop()` call.
3064[clinic start generated code]*/
3065
3066static PyObject *
3067_asyncio_get_event_loop_impl(PyObject *module)
3068/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3069{
3070 return get_event_loop();
3071}
3072
3073/*[clinic input]
3074_asyncio.get_running_loop
3075
3076Return the running event loop. Raise a RuntimeError if there is none.
3077
3078This function is thread-specific.
3079[clinic start generated code]*/
3080
3081static PyObject *
3082_asyncio_get_running_loop_impl(PyObject *module)
3083/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3084{
3085 PyObject *loop;
3086 if (get_running_loop(&loop)) {
3087 return NULL;
3088 }
3089 if (loop == NULL) {
3090 /* There's no currently running event loop */
3091 PyErr_SetString(
3092 PyExc_RuntimeError, "no running event loop");
3093 }
3094 return loop;
3095}
3096
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003097/*[clinic input]
3098_asyncio._register_task
3099
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003100 task: object
3101
3102Register a new task in asyncio as executed by loop.
3103
3104Returns None.
3105[clinic start generated code]*/
3106
3107static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003108_asyncio__register_task_impl(PyObject *module, PyObject *task)
3109/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003110{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003111 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003112 return NULL;
3113 }
3114 Py_RETURN_NONE;
3115}
3116
3117
3118/*[clinic input]
3119_asyncio._unregister_task
3120
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003121 task: object
3122
3123Unregister a task.
3124
3125Returns None.
3126[clinic start generated code]*/
3127
3128static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003129_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3130/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003131{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003132 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003133 return NULL;
3134 }
3135 Py_RETURN_NONE;
3136}
3137
3138
3139/*[clinic input]
3140_asyncio._enter_task
3141
3142 loop: object
3143 task: object
3144
3145Enter into task execution or resume suspended task.
3146
3147Task belongs to loop.
3148
3149Returns None.
3150[clinic start generated code]*/
3151
3152static PyObject *
3153_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3154/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3155{
3156 if (enter_task(loop, task) < 0) {
3157 return NULL;
3158 }
3159 Py_RETURN_NONE;
3160}
3161
3162
3163/*[clinic input]
3164_asyncio._leave_task
3165
3166 loop: object
3167 task: object
3168
3169Leave task execution or suspend a task.
3170
3171Task belongs to loop.
3172
3173Returns None.
3174[clinic start generated code]*/
3175
3176static PyObject *
3177_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3178/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3179{
3180 if (leave_task(loop, task) < 0) {
3181 return NULL;
3182 }
3183 Py_RETURN_NONE;
3184}
3185
Yury Selivanova70232f2017-12-13 14:49:42 -05003186
Yury Selivanov9d411c12018-01-23 15:10:03 -05003187/*********************** PyRunningLoopHolder ********************/
3188
3189
3190static PyRunningLoopHolder *
3191new_running_loop_holder(PyObject *loop)
3192{
3193 PyRunningLoopHolder *rl = PyObject_New(
3194 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3195 if (rl == NULL) {
3196 return NULL;
3197 }
3198
3199#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3200 rl->rl_pid = getpid();
3201#endif
3202
3203 Py_INCREF(loop);
3204 rl->rl_loop = loop;
3205
3206 return rl;
3207}
3208
3209
3210static void
3211PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3212{
3213 Py_CLEAR(rl->rl_loop);
3214 PyObject_Free(rl);
3215}
3216
3217
3218static PyTypeObject PyRunningLoopHolder_Type = {
3219 PyVarObject_HEAD_INIT(NULL, 0)
3220 "_RunningLoopHolder",
3221 sizeof(PyRunningLoopHolder),
3222 .tp_getattro = PyObject_GenericGetAttr,
3223 .tp_flags = Py_TPFLAGS_DEFAULT,
3224 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3225};
3226
3227
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003228/*********************** Module **************************/
3229
3230
3231static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003232module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003233{
3234 PyObject *next;
3235 PyObject *current;
3236
3237 next = (PyObject*) fi_freelist;
3238 while (next != NULL) {
3239 assert(fi_freelist_len > 0);
3240 fi_freelist_len--;
3241
3242 current = next;
3243 next = (PyObject*) ((futureiterobject*) current)->future;
3244 PyObject_GC_Del(current);
3245 }
3246 assert(fi_freelist_len == 0);
3247 fi_freelist = NULL;
3248}
3249
3250
3251static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003252module_free(void *m)
3253{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003254 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003255 Py_CLEAR(traceback_extract_stack);
3256 Py_CLEAR(asyncio_future_repr_info_func);
3257 Py_CLEAR(asyncio_get_event_loop_policy);
3258 Py_CLEAR(asyncio_iscoroutine_func);
3259 Py_CLEAR(asyncio_task_get_stack_func);
3260 Py_CLEAR(asyncio_task_print_stack_func);
3261 Py_CLEAR(asyncio_task_repr_info_func);
3262 Py_CLEAR(asyncio_InvalidStateError);
3263 Py_CLEAR(asyncio_CancelledError);
3264
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003265 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003266 Py_CLEAR(current_tasks);
3267 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003268
Yury Selivanovf23746a2018-01-22 19:11:18 -05003269 Py_CLEAR(context_kwname);
3270
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003271 module_free_freelists();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003272}
3273
3274static int
3275module_init(void)
3276{
3277 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003278
3279 asyncio_mod = PyImport_ImportModule("asyncio");
3280 if (asyncio_mod == NULL) {
3281 goto fail;
3282 }
Ben Harper321def82019-10-07 12:19:58 -04003283 if (module_initialized != 0) {
3284 return 0;
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02003285 }
Ben Harper321def82019-10-07 12:19:58 -04003286 else {
3287 module_initialized = 1;
3288 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003289
3290 current_tasks = PyDict_New();
3291 if (current_tasks == NULL) {
3292 goto fail;
3293 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003294
Yury Selivanova9d7e552017-12-19 07:18:45 -05003295 iscoroutine_typecache = PySet_New(NULL);
3296 if (iscoroutine_typecache == NULL) {
3297 goto fail;
3298 }
3299
Yury Selivanovf23746a2018-01-22 19:11:18 -05003300
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003301 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003302 if (context_kwname == NULL) {
3303 goto fail;
3304 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003305
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003306#define WITH_MOD(NAME) \
3307 Py_CLEAR(module); \
3308 module = PyImport_ImportModule(NAME); \
3309 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003310 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003311 }
3312
3313#define GET_MOD_ATTR(VAR, NAME) \
3314 VAR = PyObject_GetAttrString(module, NAME); \
3315 if (VAR == NULL) { \
3316 goto fail; \
3317 }
3318
3319 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003320 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003321
3322 WITH_MOD("asyncio.base_futures")
3323 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003324
3325 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003326 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3327 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3328
3329 WITH_MOD("asyncio.base_tasks")
3330 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3331 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3332 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3333
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003334 WITH_MOD("asyncio.coroutines")
3335 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3336
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003337 WITH_MOD("traceback")
3338 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3339
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003340 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003341 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003342 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003343 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003344 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003345 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003346 goto fail;
3347 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003348
Serhiy Storchakabca49392017-09-03 08:10:14 +03003349 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003350 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003351
INADA Naokic411a7d2016-10-18 11:48:14 +09003352fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003353 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003354 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003355 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003356
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003357#undef WITH_MOD
3358#undef GET_MOD_ATTR
3359}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003360
INADA Naokic411a7d2016-10-18 11:48:14 +09003361PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003362
Yury Selivanova70232f2017-12-13 14:49:42 -05003363static PyMethodDef asyncio_methods[] = {
3364 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3365 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3366 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3367 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003368 _ASYNCIO__REGISTER_TASK_METHODDEF
3369 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3370 _ASYNCIO__ENTER_TASK_METHODDEF
3371 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003372 {NULL, NULL}
3373};
3374
INADA Naoki9f2ce252016-10-15 15:39:19 +09003375static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003376 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003377 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003378 module_doc, /* m_doc */
3379 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003380 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003381 NULL, /* m_slots */
3382 NULL, /* m_traverse */
3383 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003384 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003385};
3386
3387
3388PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003389PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003390{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003391 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003392 return NULL;
3393 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003394 if (PyType_Ready(&FutureType) < 0) {
3395 return NULL;
3396 }
3397 if (PyType_Ready(&FutureIterType) < 0) {
3398 return NULL;
3399 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003400 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003401 return NULL;
3402 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003403 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003404 return NULL;
3405 }
3406 if (PyType_Ready(&TaskType) < 0) {
3407 return NULL;
3408 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003409 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3410 return NULL;
3411 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003412
INADA Naoki9f2ce252016-10-15 15:39:19 +09003413 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003414 if (m == NULL) {
3415 return NULL;
3416 }
3417
3418 Py_INCREF(&FutureType);
3419 if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
3420 Py_DECREF(&FutureType);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003421 Py_DECREF(m);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003422 return NULL;
3423 }
3424
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003425 Py_INCREF(&TaskType);
3426 if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
3427 Py_DECREF(&TaskType);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003428 Py_DECREF(m);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003429 return NULL;
3430 }
3431
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003432 Py_INCREF(all_tasks);
3433 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3434 Py_DECREF(all_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003435 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003436 return NULL;
3437 }
3438
3439 Py_INCREF(current_tasks);
3440 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3441 Py_DECREF(current_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003442 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003443 return NULL;
3444 }
3445
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003446 return m;
3447}