blob: 01e36c656da8fb83eab7f9bb67807e8b43530862 [file] [log] [blame]
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001#include "Python.h"
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002#include "pycore_pyerrors.h" // _PyErr_ClearExcState()
Victor Stinner4a21e572020-04-15 02:35:41 +02003#include <stddef.h> // offsetof()
INADA Naoki9e4e38e2016-10-09 14:44:47 +09004
5
Yury Selivanova0c1ba62016-10-28 12:52:37 -04006/*[clinic input]
7module _asyncio
8[clinic start generated code]*/
9/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
10
11
INADA Naoki9e4e38e2016-10-09 14:44:47 +090012/* identifiers used from some functions */
Yury Selivanova70232f2017-12-13 14:49:42 -050013_Py_IDENTIFIER(__asyncio_running_event_loop__);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +030014_Py_IDENTIFIER(_asyncio_future_blocking);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040015_Py_IDENTIFIER(add_done_callback);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090016_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040017_Py_IDENTIFIER(cancel);
Yury Selivanova70232f2017-12-13 14:49:42 -050018_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040019_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090020
21
INADA Naoki9f2ce252016-10-15 15:39:19 +090022/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020023static PyObject *asyncio_mod;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020024static PyObject *traceback_extract_stack;
25static PyObject *asyncio_get_event_loop_policy;
26static PyObject *asyncio_future_repr_info_func;
27static PyObject *asyncio_iscoroutine_func;
28static PyObject *asyncio_task_get_stack_func;
29static PyObject *asyncio_task_print_stack_func;
30static PyObject *asyncio_task_repr_info_func;
31static PyObject *asyncio_InvalidStateError;
32static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050033static PyObject *context_kwname;
Ben Harper321def82019-10-07 12:19:58 -040034static int module_initialized;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020035
Yury Selivanov9d411c12018-01-23 15:10:03 -050036static PyObject *cached_running_holder;
37static volatile uint64_t cached_running_holder_tsid;
38
Alex Grönholmcca4eec2018-08-09 00:06:47 +030039/* Counter for autogenerated Task names */
40static uint64_t task_name_counter = 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020041
Yury Selivanovca9b36c2017-12-23 15:04:15 -050042/* WeakSet containing all alive tasks. */
43static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020044
45/* Dictionary containing tasks that are currently active in
46 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050047static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090048
Yury Selivanova9d7e552017-12-19 07:18:45 -050049/* An isinstance type cache for the 'is_coroutine()' function. */
50static PyObject *iscoroutine_typecache;
51
INADA Naoki9e4e38e2016-10-09 14:44:47 +090052
INADA Naoki9e4e38e2016-10-09 14:44:47 +090053typedef enum {
54 STATE_PENDING,
55 STATE_CANCELLED,
56 STATE_FINISHED
57} fut_state;
58
Yury Selivanova0c1ba62016-10-28 12:52:37 -040059#define FutureObj_HEAD(prefix) \
60 PyObject_HEAD \
61 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050062 PyObject *prefix##_callback0; \
Yury Selivanov994269c2018-09-27 14:55:55 -040063 PyObject *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040064 PyObject *prefix##_callbacks; \
65 PyObject *prefix##_exception; \
66 PyObject *prefix##_result; \
67 PyObject *prefix##_source_tb; \
Chris Jerdonek1ce58412020-05-15 16:55:50 -070068 PyObject *prefix##_cancel_msg; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040069 fut_state prefix##_state; \
70 int prefix##_log_tb; \
71 int prefix##_blocking; \
72 PyObject *dict; \
Chris Jerdonekda742ba2020-05-17 22:47:31 -070073 PyObject *prefix##_weakreflist; \
74 _PyErr_StackItem prefix##_cancelled_exc_state;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040075
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
Yury Selivanov9d411c12018-01-23 15:10:03 -050098 PyObject *rl_loop;
99#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
100 pid_t rl_pid;
101#endif
102} PyRunningLoopHolder;
103
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400104
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500105static PyTypeObject FutureType;
106static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500107static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500108
109
Dong-hee Na1b55b652020-02-17 19:09:15 +0900110#define Future_CheckExact(obj) Py_IS_TYPE(obj, &FutureType)
111#define Task_CheckExact(obj) Py_IS_TYPE(obj, &TaskType)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500112
113#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
114#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
115
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400116#include "clinic/_asynciomodule.c.h"
117
118
119/*[clinic input]
120class _asyncio.Future "FutureObj *" "&Future_Type"
121[clinic start generated code]*/
122/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
123
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500124
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400125/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500126static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900127
Yury Selivanov9d411c12018-01-23 15:10:03 -0500128static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
129
Yury Selivanova70232f2017-12-13 14:49:42 -0500130
131static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500132_is_coroutine(PyObject *coro)
133{
134 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
135 to check if it's another coroutine flavour.
136
137 Do this check after 'future_init()'; in case we need to raise
138 an error, __del__ needs a properly initialized object.
139 */
Petr Viktorinffd97532020-02-11 17:46:57 +0100140 PyObject *res = PyObject_CallOneArg(asyncio_iscoroutine_func, coro);
Yury Selivanova9d7e552017-12-19 07:18:45 -0500141 if (res == NULL) {
142 return -1;
143 }
144
145 int is_res_true = PyObject_IsTrue(res);
146 Py_DECREF(res);
147 if (is_res_true <= 0) {
148 return is_res_true;
149 }
150
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200151 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500152 /* Just in case we don't want to cache more than 100
153 positive types. That shouldn't ever happen, unless
154 someone stressing the system on purpose.
155 */
156 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
157 return -1;
158 }
159 }
160
161 return 1;
162}
163
164
165static inline int
166is_coroutine(PyObject *coro)
167{
168 if (PyCoro_CheckExact(coro)) {
169 return 1;
170 }
171
172 /* Check if `type(coro)` is in the cache.
173 Caching makes is_coroutine() function almost as fast as
174 PyCoro_CheckExact() for non-native coroutine-like objects
175 (like coroutines compiled with Cython).
176
177 asyncio.iscoroutine() has its own type caching mechanism.
178 This cache allows us to avoid the cost of even calling
179 a pure-Python function in 99.9% cases.
180 */
181 int has_it = PySet_Contains(
182 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
183 if (has_it == 0) {
184 /* type(coro) is not in iscoroutine_typecache */
185 return _is_coroutine(coro);
186 }
187
Leo Ariasc3d95082018-02-03 18:36:10 -0600188 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500189 type(coro) is in iscoroutine_typecache
190 */
191 return has_it;
192}
193
194
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500195static PyObject *
196get_future_loop(PyObject *fut)
197{
198 /* Implementation of `asyncio.futures._get_loop` */
199
200 _Py_IDENTIFIER(get_loop);
201 _Py_IDENTIFIER(_loop);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300202 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500203
204 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
205 PyObject *loop = ((FutureObj *)fut)->fut_loop;
206 Py_INCREF(loop);
207 return loop;
208 }
209
Serhiy Storchaka66553542018-05-20 16:30:31 +0300210 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
211 return NULL;
212 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500213 if (getloop != NULL) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200214 PyObject *res = PyObject_CallNoArgs(getloop);
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500215 Py_DECREF(getloop);
216 return res;
217 }
218
219 return _PyObject_GetAttrId(fut, &PyId__loop);
220}
221
222
Yury Selivanova9d7e552017-12-19 07:18:45 -0500223static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500224get_running_loop(PyObject **loop)
225{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500226 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500227
Yury Selivanov9d411c12018-01-23 15:10:03 -0500228 PyThreadState *ts = PyThreadState_Get();
Victor Stinner5c3cda02020-03-25 21:23:53 +0100229 uint64_t ts_id = PyThreadState_GetID(ts);
230 if (ts_id == cached_running_holder_tsid && cached_running_holder != NULL) {
Yury Selivanov9d411c12018-01-23 15:10:03 -0500231 // Fast path, check the cache.
232 rl = cached_running_holder; // borrowed
233 }
234 else {
Victor Stinner0e427c62020-03-25 21:22:55 +0100235 PyObject *ts_dict = _PyThreadState_GetDict(ts); // borrowed
236 if (ts_dict == NULL) {
Yury Selivanov9d411c12018-01-23 15:10:03 -0500237 goto not_found;
238 }
239
240 rl = _PyDict_GetItemIdWithError(
Victor Stinner0e427c62020-03-25 21:22:55 +0100241 ts_dict, &PyId___asyncio_running_event_loop__); // borrowed
Yury Selivanov9d411c12018-01-23 15:10:03 -0500242 if (rl == NULL) {
243 if (PyErr_Occurred()) {
244 goto error;
245 }
246 else {
247 goto not_found;
248 }
249 }
250
251 cached_running_holder = rl; // borrowed
Victor Stinner5c3cda02020-03-25 21:23:53 +0100252 cached_running_holder_tsid = ts_id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500253 }
254
Dong-hee Na1b55b652020-02-17 19:09:15 +0900255 assert(Py_IS_TYPE(rl, &PyRunningLoopHolder_Type));
Yury Selivanov9d411c12018-01-23 15:10:03 -0500256 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500257
258 if (running_loop == Py_None) {
259 goto not_found;
260 }
261
Yury Selivanov9d411c12018-01-23 15:10:03 -0500262#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
263 /* On Windows there is no getpid, but there is also no os.fork(),
264 so there is no need for this check.
265 */
266 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
267 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500268 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500269#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500270
Yury Selivanov9d411c12018-01-23 15:10:03 -0500271 Py_INCREF(running_loop);
272 *loop = running_loop;
273 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500274
275not_found:
276 *loop = NULL;
277 return 0;
278
Yury Selivanova70232f2017-12-13 14:49:42 -0500279error:
280 *loop = NULL;
281 return -1;
282}
283
284
285static int
286set_running_loop(PyObject *loop)
287{
Tony Solomonik529f4262020-07-08 22:27:31 +0300288 PyObject *ts_dict = NULL;
Yury Selivanova70232f2017-12-13 14:49:42 -0500289
Tony Solomonik529f4262020-07-08 22:27:31 +0300290 PyThreadState *tstate = PyThreadState_Get();
291 if (tstate != NULL) {
292 ts_dict = _PyThreadState_GetDict(tstate); // borrowed
293 }
294
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
Tony Solomonik529f4262020-07-08 22:27:31 +0300314 cached_running_holder = (PyObject *)rl;
315 cached_running_holder_tsid = PyThreadState_GetID(tstate);
316
Yury Selivanova70232f2017-12-13 14:49:42 -0500317 return 0;
318}
319
320
321static PyObject *
322get_event_loop(void)
323{
324 PyObject *loop;
325 PyObject *policy;
326
327 if (get_running_loop(&loop)) {
328 return NULL;
329 }
330 if (loop != NULL) {
331 return loop;
332 }
333
Victor Stinner2ff58a22019-06-17 14:27:23 +0200334 policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy);
Yury Selivanova70232f2017-12-13 14:49:42 -0500335 if (policy == NULL) {
336 return NULL;
337 }
338
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200339 loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
Yury Selivanova70232f2017-12-13 14:49:42 -0500340 Py_DECREF(policy);
341 return loop;
342}
343
344
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900345static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400346call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500347{
348 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500349 PyObject *stack[3];
350 Py_ssize_t nargs;
351
352 if (ctx == NULL) {
353 handle = _PyObject_CallMethodIdObjArgs(
354 loop, &PyId_call_soon, func, arg, NULL);
355 }
356 else {
357 /* Use FASTCALL to pass a keyword-only argument to call_soon */
358
359 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
360 if (callable == NULL) {
361 return -1;
362 }
363
364 /* All refs in 'stack' are borrowed. */
365 nargs = 1;
366 stack[0] = func;
367 if (arg != NULL) {
368 stack[1] = arg;
369 nargs++;
370 }
371 stack[nargs] = (PyObject *)ctx;
372
Petr Viktorinffd97532020-02-11 17:46:57 +0100373 handle = PyObject_Vectorcall(callable, stack, nargs, context_kwname);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500374 Py_DECREF(callable);
375 }
376
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500377 if (handle == NULL) {
378 return -1;
379 }
380 Py_DECREF(handle);
381 return 0;
382}
383
384
385static inline int
386future_is_alive(FutureObj *fut)
387{
388 return fut->fut_loop != NULL;
389}
390
391
392static inline int
393future_ensure_alive(FutureObj *fut)
394{
395 if (!future_is_alive(fut)) {
396 PyErr_SetString(PyExc_RuntimeError,
397 "Future object is not initialized.");
398 return -1;
399 }
400 return 0;
401}
402
403
404#define ENSURE_FUTURE_ALIVE(fut) \
405 do { \
406 assert(Future_Check(fut) || Task_Check(fut)); \
407 if (future_ensure_alive((FutureObj*)fut)) { \
408 return NULL; \
409 } \
410 } while(0);
411
412
413static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400414future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900415{
416 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500417 Py_ssize_t i;
418
419 if (fut->fut_callback0 != NULL) {
420 /* There's a 1st callback */
421
422 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500423 fut->fut_loop, fut->fut_callback0,
424 (PyObject *)fut, fut->fut_context0);
425
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500426 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500427 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500428 if (ret) {
429 /* If an error occurs in pure-Python implementation,
430 all callbacks are cleared. */
431 Py_CLEAR(fut->fut_callbacks);
432 return ret;
433 }
434
435 /* we called the first callback, now try calling
436 callbacks from the 'fut_callbacks' list. */
437 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900438
439 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500440 /* No more callbacks, return. */
441 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900442 }
443
444 len = PyList_GET_SIZE(fut->fut_callbacks);
445 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500446 /* The list of callbacks was empty; clear it and return. */
447 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900448 return 0;
449 }
450
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900451 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500452 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
453 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
454 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900455
Yury Selivanov994269c2018-09-27 14:55:55 -0400456 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500457 /* If an error occurs in pure-Python implementation,
458 all callbacks are cleared. */
459 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900460 return -1;
461 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900462 }
463
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500464 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900465 return 0;
466}
467
Oren Milmand019bc82018-02-13 12:28:33 +0200468
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900469static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400470future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900471{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300472 PyObject *res;
473 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900474 _Py_IDENTIFIER(get_debug);
475
Oren Milmand019bc82018-02-13 12:28:33 +0200476 // Same to FutureObj_clear() but not clearing fut->dict
477 Py_CLEAR(fut->fut_loop);
478 Py_CLEAR(fut->fut_callback0);
479 Py_CLEAR(fut->fut_context0);
480 Py_CLEAR(fut->fut_callbacks);
481 Py_CLEAR(fut->fut_result);
482 Py_CLEAR(fut->fut_exception);
483 Py_CLEAR(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700484 Py_CLEAR(fut->fut_cancel_msg);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700485 _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
Oren Milmand019bc82018-02-13 12:28:33 +0200486
487 fut->fut_state = STATE_PENDING;
488 fut->fut_log_tb = 0;
489 fut->fut_blocking = 0;
490
Serhiy Storchakabca49392017-09-03 08:10:14 +0300491 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500492 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900493 if (loop == NULL) {
494 return -1;
495 }
496 }
497 else {
498 Py_INCREF(loop);
499 }
Oren Milmand019bc82018-02-13 12:28:33 +0200500 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900501
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200502 res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900503 if (res == NULL) {
504 return -1;
505 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300506 is_true = PyObject_IsTrue(res);
507 Py_DECREF(res);
508 if (is_true < 0) {
509 return -1;
510 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400511 if (is_true && !_Py_IsFinalizing()) {
512 /* Only try to capture the traceback if the interpreter is not being
513 finalized. The original motivation to add a `_Py_IsFinalizing()`
514 call was to prevent SIGSEGV when a Future is created in a __del__
515 method, which is called during the interpreter shutdown and the
516 traceback module is already unloaded.
517 */
Victor Stinner2ff58a22019-06-17 14:27:23 +0200518 fut->fut_source_tb = PyObject_CallNoArgs(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900519 if (fut->fut_source_tb == NULL) {
520 return -1;
521 }
522 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900523
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900524 return 0;
525}
526
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900527static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400528future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900529{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500530 if (future_ensure_alive(fut)) {
531 return NULL;
532 }
533
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900534 if (fut->fut_state != STATE_PENDING) {
535 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
536 return NULL;
537 }
538
Serhiy Storchakabca49392017-09-03 08:10:14 +0300539 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900540 Py_INCREF(res);
541 fut->fut_result = res;
542 fut->fut_state = STATE_FINISHED;
543
Yury Selivanov22feeb82018-01-24 11:31:01 -0500544 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900545 return NULL;
546 }
547 Py_RETURN_NONE;
548}
549
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900550static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400551future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900552{
553 PyObject *exc_val = NULL;
554
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900555 if (fut->fut_state != STATE_PENDING) {
556 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
557 return NULL;
558 }
559
560 if (PyExceptionClass_Check(exc)) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200561 exc_val = PyObject_CallNoArgs(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900562 if (exc_val == NULL) {
563 return NULL;
564 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300565 if (fut->fut_state != STATE_PENDING) {
566 Py_DECREF(exc_val);
567 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
568 return NULL;
569 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900570 }
571 else {
572 exc_val = exc;
573 Py_INCREF(exc_val);
574 }
575 if (!PyExceptionInstance_Check(exc_val)) {
576 Py_DECREF(exc_val);
577 PyErr_SetString(PyExc_TypeError, "invalid exception object");
578 return NULL;
579 }
Andy Lesterdffe4c02020-03-04 07:15:20 -0600580 if (Py_IS_TYPE(exc_val, (PyTypeObject *)PyExc_StopIteration)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900581 Py_DECREF(exc_val);
582 PyErr_SetString(PyExc_TypeError,
583 "StopIteration interacts badly with generators "
584 "and cannot be raised into a Future");
585 return NULL;
586 }
587
Serhiy Storchakabca49392017-09-03 08:10:14 +0300588 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900589 fut->fut_exception = exc_val;
590 fut->fut_state = STATE_FINISHED;
591
Yury Selivanov22feeb82018-01-24 11:31:01 -0500592 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900593 return NULL;
594 }
595
596 fut->fut_log_tb = 1;
597 Py_RETURN_NONE;
598}
599
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700600static PyObject *
601create_cancelled_error(PyObject *msg)
602{
603 PyObject *exc;
604 if (msg == NULL || msg == Py_None) {
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700605 exc = PyObject_CallNoArgs(asyncio_CancelledError);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700606 } else {
607 exc = PyObject_CallOneArg(asyncio_CancelledError, msg);
608 }
609 return exc;
610}
611
612static void
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700613future_set_cancelled_error(FutureObj *fut)
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700614{
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700615 PyObject *exc = create_cancelled_error(fut->fut_cancel_msg);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700616 PyErr_SetObject(asyncio_CancelledError, exc);
617 Py_DECREF(exc);
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700618
619 _PyErr_ChainStackItem(&fut->fut_cancelled_exc_state);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700620}
621
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400622static int
623future_get_result(FutureObj *fut, PyObject **result)
624{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400625 if (fut->fut_state == STATE_CANCELLED) {
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700626 future_set_cancelled_error(fut);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300627 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400628 }
629
630 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300631 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
632 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400633 }
634
635 fut->fut_log_tb = 0;
636 if (fut->fut_exception != NULL) {
637 Py_INCREF(fut->fut_exception);
638 *result = fut->fut_exception;
639 return 1;
640 }
641
642 Py_INCREF(fut->fut_result);
643 *result = fut->fut_result;
644 return 0;
645}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900646
647static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400648future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900649{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500650 if (!future_is_alive(fut)) {
651 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
652 return NULL;
653 }
654
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900655 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500656 /* The future is done/cancelled, so schedule the callback
657 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500658 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900659 return NULL;
660 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900661 }
662 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500663 /* The future is pending, add a callback.
664
665 Callbacks in the future object are stored as follows:
666
667 callback0 -- a pointer to the first callback
668 callbacks -- a list of 2nd, 3rd, ... callbacks
669
670 Invariants:
671
672 * callbacks != NULL:
673 There are some callbacks in in the list. Just
674 add the new callback to it.
675
676 * callbacks == NULL and callback0 == NULL:
677 This is the first callback. Set it to callback0.
678
679 * callbacks == NULL and callback0 != NULL:
680 This is a second callback. Initialize callbacks
681 with a new list and add the new callback to it.
682 */
683
Yury Selivanovf23746a2018-01-22 19:11:18 -0500684 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500685 Py_INCREF(arg);
686 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500687 Py_INCREF(ctx);
688 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500689 }
690 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500691 PyObject *tup = PyTuple_New(2);
692 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500693 return NULL;
694 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500695 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500696 PyTuple_SET_ITEM(tup, 0, arg);
697 Py_INCREF(ctx);
698 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
699
700 if (fut->fut_callbacks != NULL) {
701 int err = PyList_Append(fut->fut_callbacks, tup);
702 if (err) {
703 Py_DECREF(tup);
704 return NULL;
705 }
706 Py_DECREF(tup);
707 }
708 else {
709 fut->fut_callbacks = PyList_New(1);
710 if (fut->fut_callbacks == NULL) {
Zackery Spytz7b78e7f2020-05-30 02:22:02 -0600711 Py_DECREF(tup);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500712 return NULL;
713 }
714
715 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
716 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900717 }
718 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500719
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900720 Py_RETURN_NONE;
721}
722
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400723static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700724future_cancel(FutureObj *fut, PyObject *msg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400725{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000726 fut->fut_log_tb = 0;
727
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400728 if (fut->fut_state != STATE_PENDING) {
729 Py_RETURN_FALSE;
730 }
731 fut->fut_state = STATE_CANCELLED;
732
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700733 Py_XINCREF(msg);
734 Py_XSETREF(fut->fut_cancel_msg, msg);
735
Yury Selivanov22feeb82018-01-24 11:31:01 -0500736 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400737 return NULL;
738 }
739
740 Py_RETURN_TRUE;
741}
742
743/*[clinic input]
744_asyncio.Future.__init__
745
746 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300747 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400748
749This class is *almost* compatible with concurrent.futures.Future.
750
751 Differences:
752
753 - result() and exception() do not take a timeout argument and
754 raise an exception when the future isn't done yet.
755
756 - Callbacks registered with add_done_callback() are always called
757 via the event loop's call_soon_threadsafe().
758
759 - This class is not compatible with the wait() and as_completed()
760 methods in the concurrent.futures package.
761[clinic start generated code]*/
762
763static int
764_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300765/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400766
767{
768 return future_init(self, loop);
769}
770
771static int
772FutureObj_clear(FutureObj *fut)
773{
774 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500775 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500776 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400777 Py_CLEAR(fut->fut_callbacks);
778 Py_CLEAR(fut->fut_result);
779 Py_CLEAR(fut->fut_exception);
780 Py_CLEAR(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700781 Py_CLEAR(fut->fut_cancel_msg);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700782 _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400783 Py_CLEAR(fut->dict);
784 return 0;
785}
786
787static int
788FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
789{
790 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500791 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500792 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400793 Py_VISIT(fut->fut_callbacks);
794 Py_VISIT(fut->fut_result);
795 Py_VISIT(fut->fut_exception);
796 Py_VISIT(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700797 Py_VISIT(fut->fut_cancel_msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400798 Py_VISIT(fut->dict);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700799
800 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
801 Py_VISIT(exc_state->exc_type);
802 Py_VISIT(exc_state->exc_value);
803 Py_VISIT(exc_state->exc_traceback);
804
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400805 return 0;
806}
807
808/*[clinic input]
809_asyncio.Future.result
810
811Return the result this future represents.
812
813If the future has been cancelled, raises CancelledError. If the
814future's result isn't yet available, raises InvalidStateError. If
815the future is done and has an exception set, this exception is raised.
816[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900817
818static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400819_asyncio_Future_result_impl(FutureObj *self)
820/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
821{
822 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500823
824 if (!future_is_alive(self)) {
825 PyErr_SetString(asyncio_InvalidStateError,
826 "Future object is not initialized.");
827 return NULL;
828 }
829
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400830 int res = future_get_result(self, &result);
831
832 if (res == -1) {
833 return NULL;
834 }
835
836 if (res == 0) {
837 return result;
838 }
839
840 assert(res == 1);
841
842 PyErr_SetObject(PyExceptionInstance_Class(result), result);
843 Py_DECREF(result);
844 return NULL;
845}
846
847/*[clinic input]
848_asyncio.Future.exception
849
850Return the exception that was set on this future.
851
852The exception (or None if no exception was set) is returned only if
853the future is done. If the future has been cancelled, raises
854CancelledError. If the future isn't done yet, raises
855InvalidStateError.
856[clinic start generated code]*/
857
858static PyObject *
859_asyncio_Future_exception_impl(FutureObj *self)
860/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
861{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500862 if (!future_is_alive(self)) {
863 PyErr_SetString(asyncio_InvalidStateError,
864 "Future object is not initialized.");
865 return NULL;
866 }
867
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400868 if (self->fut_state == STATE_CANCELLED) {
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700869 future_set_cancelled_error(self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400870 return NULL;
871 }
872
873 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300874 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400875 return NULL;
876 }
877
878 if (self->fut_exception != NULL) {
879 self->fut_log_tb = 0;
880 Py_INCREF(self->fut_exception);
881 return self->fut_exception;
882 }
883
884 Py_RETURN_NONE;
885}
886
887/*[clinic input]
888_asyncio.Future.set_result
889
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500890 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400891 /
892
893Mark the future done and set its result.
894
895If the future is already done when this method is called, raises
896InvalidStateError.
897[clinic start generated code]*/
898
899static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500900_asyncio_Future_set_result(FutureObj *self, PyObject *result)
901/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400902{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500903 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500904 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400905}
906
907/*[clinic input]
908_asyncio.Future.set_exception
909
Serhiy Storchakabca49392017-09-03 08:10:14 +0300910 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400911 /
912
913Mark the future done and set an exception.
914
915If the future is already done when this method is called, raises
916InvalidStateError.
917[clinic start generated code]*/
918
919static PyObject *
920_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300921/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400922{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500923 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400924 return future_set_exception(self, exception);
925}
926
927/*[clinic input]
928_asyncio.Future.add_done_callback
929
Serhiy Storchakabca49392017-09-03 08:10:14 +0300930 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400931 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500932 *
933 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400934
935Add a callback to be run when the future becomes done.
936
937The callback is called with a single argument - the future object. If
938the future is already done when this is called, the callback is
939scheduled with call_soon.
940[clinic start generated code]*/
941
942static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500943_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
944 PyObject *context)
945/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400946{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500947 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400948 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500949 if (context == NULL) {
950 return NULL;
951 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400952 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500953 Py_DECREF(context);
954 return res;
955 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400956 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400957}
958
959/*[clinic input]
960_asyncio.Future.remove_done_callback
961
Serhiy Storchakabca49392017-09-03 08:10:14 +0300962 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400963 /
964
965Remove all instances of a callback from the "call when done" list.
966
967Returns the number of callbacks removed.
968[clinic start generated code]*/
969
970static PyObject *
971_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300972/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900973{
974 PyObject *newlist;
975 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500976 Py_ssize_t cleared_callback0 = 0;
977
978 ENSURE_FUTURE_ALIVE(self)
979
980 if (self->fut_callback0 != NULL) {
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300981 int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500982 if (cmp == -1) {
983 return NULL;
984 }
985 if (cmp == 1) {
986 /* callback0 == fn */
987 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500988 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500989 cleared_callback0 = 1;
990 }
991 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900992
Serhiy Storchakabca49392017-09-03 08:10:14 +0300993 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500994 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300995 }
996
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400997 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900998 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500999 Py_CLEAR(self->fut_callbacks);
1000 return PyLong_FromSsize_t(cleared_callback0);
1001 }
1002
1003 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -05001004 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001005 int cmp = PyObject_RichCompareBool(
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001006 PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001007 if (cmp == -1) {
1008 return NULL;
1009 }
1010 if (cmp == 1) {
1011 /* callbacks[0] == fn */
1012 Py_CLEAR(self->fut_callbacks);
1013 return PyLong_FromSsize_t(1 + cleared_callback0);
1014 }
1015 /* callbacks[0] != fn and len(callbacks) == 1 */
1016 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001017 }
1018
1019 newlist = PyList_New(len);
1020 if (newlist == NULL) {
1021 return NULL;
1022 }
1023
Yury Selivanov84af9032017-03-02 23:46:56 -05001024 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001025 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001026 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001027 Py_INCREF(item);
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001028 ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001029 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001030 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001031 PyList_SET_ITEM(newlist, j, item);
1032 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001033 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -04001034 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001035 ret = PyList_Append(newlist, item);
1036 }
1037 Py_DECREF(item);
1038 if (ret < 0) {
1039 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001040 }
1041 }
1042
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001043 if (j == 0) {
1044 Py_CLEAR(self->fut_callbacks);
1045 Py_DECREF(newlist);
1046 return PyLong_FromSsize_t(len + cleared_callback0);
1047 }
1048
Serhiy Storchakabca49392017-09-03 08:10:14 +03001049 if (j < len) {
Victor Stinner60ac6ed2020-02-07 23:18:08 +01001050 Py_SET_SIZE(newlist, j);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001051 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001052 j = PyList_GET_SIZE(newlist);
1053 len = PyList_GET_SIZE(self->fut_callbacks);
1054 if (j != len) {
1055 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1056 goto fail;
1057 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001058 }
1059 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001060 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001061
1062fail:
1063 Py_DECREF(newlist);
1064 return NULL;
1065}
1066
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001067/*[clinic input]
1068_asyncio.Future.cancel
1069
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001070 msg: object = None
1071
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001072Cancel the future and schedule callbacks.
1073
1074If the future is already done or cancelled, return False. Otherwise,
1075change the future's state to cancelled, schedule the callbacks and
1076return True.
1077[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001078
1079static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001080_asyncio_Future_cancel_impl(FutureObj *self, PyObject *msg)
1081/*[clinic end generated code: output=3edebbc668e5aba3 input=925eb545251f2c5a]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001082{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001083 ENSURE_FUTURE_ALIVE(self)
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001084 return future_cancel(self, msg);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001085}
1086
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001087/*[clinic input]
1088_asyncio.Future.cancelled
1089
1090Return True if the future was cancelled.
1091[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001092
1093static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001094_asyncio_Future_cancelled_impl(FutureObj *self)
1095/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001096{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001097 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001098 Py_RETURN_TRUE;
1099 }
1100 else {
1101 Py_RETURN_FALSE;
1102 }
1103}
1104
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001105/*[clinic input]
1106_asyncio.Future.done
1107
1108Return True if the future is done.
1109
1110Done means either that a result / exception are available, or that the
1111future was cancelled.
1112[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001113
1114static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001115_asyncio_Future_done_impl(FutureObj *self)
1116/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001117{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001118 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001119 Py_RETURN_FALSE;
1120 }
1121 else {
1122 Py_RETURN_TRUE;
1123 }
1124}
1125
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001126/*[clinic input]
1127_asyncio.Future.get_loop
1128
1129Return the event loop the Future is bound to.
1130[clinic start generated code]*/
1131
1132static PyObject *
1133_asyncio_Future_get_loop_impl(FutureObj *self)
1134/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1135{
Andrew Svetlovdad6be52019-11-13 23:36:46 +02001136 ENSURE_FUTURE_ALIVE(self)
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001137 Py_INCREF(self->fut_loop);
1138 return self->fut_loop;
1139}
1140
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001141static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001142FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001143{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001144 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001145 Py_RETURN_TRUE;
1146 }
1147 else {
1148 Py_RETURN_FALSE;
1149 }
1150}
1151
1152static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001153FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001154{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001155 if (future_ensure_alive(fut)) {
1156 return -1;
1157 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001158 if (val == NULL) {
1159 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1160 return -1;
1161 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001162
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001163 int is_true = PyObject_IsTrue(val);
1164 if (is_true < 0) {
1165 return -1;
1166 }
1167 fut->fut_blocking = is_true;
1168 return 0;
1169}
1170
1171static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001172FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001173{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001174 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001175 if (fut->fut_log_tb) {
1176 Py_RETURN_TRUE;
1177 }
1178 else {
1179 Py_RETURN_FALSE;
1180 }
1181}
1182
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001183static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001184FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001185{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001186 if (val == NULL) {
1187 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1188 return -1;
1189 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001190 int is_true = PyObject_IsTrue(val);
1191 if (is_true < 0) {
1192 return -1;
1193 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001194 if (is_true) {
1195 PyErr_SetString(PyExc_ValueError,
1196 "_log_traceback can only be set to False");
1197 return -1;
1198 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001199 fut->fut_log_tb = is_true;
1200 return 0;
1201}
1202
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001203static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001204FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001205{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001206 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001207 Py_RETURN_NONE;
1208 }
1209 Py_INCREF(fut->fut_loop);
1210 return fut->fut_loop;
1211}
1212
1213static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001214FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001215{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001216 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001217
1218 ENSURE_FUTURE_ALIVE(fut)
1219
Yury Selivanovf23746a2018-01-22 19:11:18 -05001220 if (fut->fut_callback0 == NULL) {
1221 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001222 Py_RETURN_NONE;
1223 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001224
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001225 Py_INCREF(fut->fut_callbacks);
1226 return fut->fut_callbacks;
1227 }
1228
Yury Selivanovf23746a2018-01-22 19:11:18 -05001229 Py_ssize_t len = 1;
1230 if (fut->fut_callbacks != NULL) {
1231 len += PyList_GET_SIZE(fut->fut_callbacks);
1232 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001233
Yury Selivanovf23746a2018-01-22 19:11:18 -05001234
1235 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001236 if (new_list == NULL) {
1237 return NULL;
1238 }
1239
Yury Selivanovf23746a2018-01-22 19:11:18 -05001240 PyObject *tup0 = PyTuple_New(2);
1241 if (tup0 == NULL) {
1242 Py_DECREF(new_list);
1243 return NULL;
1244 }
1245
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001246 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001247 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1248 assert(fut->fut_context0 != NULL);
1249 Py_INCREF(fut->fut_context0);
1250 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1251
1252 PyList_SET_ITEM(new_list, 0, tup0);
1253
1254 if (fut->fut_callbacks != NULL) {
1255 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1256 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1257 Py_INCREF(cb);
1258 PyList_SET_ITEM(new_list, i + 1, cb);
1259 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001260 }
1261
1262 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001263}
1264
1265static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001266FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001267{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001268 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001269 if (fut->fut_result == NULL) {
1270 Py_RETURN_NONE;
1271 }
1272 Py_INCREF(fut->fut_result);
1273 return fut->fut_result;
1274}
1275
1276static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001277FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001278{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001279 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001280 if (fut->fut_exception == NULL) {
1281 Py_RETURN_NONE;
1282 }
1283 Py_INCREF(fut->fut_exception);
1284 return fut->fut_exception;
1285}
1286
1287static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001288FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001289{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001290 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001291 Py_RETURN_NONE;
1292 }
1293 Py_INCREF(fut->fut_source_tb);
1294 return fut->fut_source_tb;
1295}
1296
1297static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001298FutureObj_get_cancel_message(FutureObj *fut, void *Py_UNUSED(ignored))
1299{
1300 if (fut->fut_cancel_msg == NULL) {
1301 Py_RETURN_NONE;
1302 }
1303 Py_INCREF(fut->fut_cancel_msg);
1304 return fut->fut_cancel_msg;
1305}
1306
1307static int
1308FutureObj_set_cancel_message(FutureObj *fut, PyObject *msg,
1309 void *Py_UNUSED(ignored))
1310{
1311 if (msg == NULL) {
1312 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1313 return -1;
1314 }
1315 Py_INCREF(msg);
1316 Py_XSETREF(fut->fut_cancel_msg, msg);
1317 return 0;
1318}
1319
1320static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001321FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001322{
1323 _Py_IDENTIFIER(PENDING);
1324 _Py_IDENTIFIER(CANCELLED);
1325 _Py_IDENTIFIER(FINISHED);
1326 PyObject *ret = NULL;
1327
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001328 ENSURE_FUTURE_ALIVE(fut)
1329
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001330 switch (fut->fut_state) {
1331 case STATE_PENDING:
1332 ret = _PyUnicode_FromId(&PyId_PENDING);
1333 break;
1334 case STATE_CANCELLED:
1335 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1336 break;
1337 case STATE_FINISHED:
1338 ret = _PyUnicode_FromId(&PyId_FINISHED);
1339 break;
1340 default:
1341 assert (0);
1342 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001343 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001344 return ret;
1345}
1346
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001347/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001348_asyncio.Future._make_cancelled_error
1349
1350Create the CancelledError to raise if the Future is cancelled.
1351
1352This should only be called once when handling a cancellation since
1353it erases the context exception value.
1354[clinic start generated code]*/
1355
1356static PyObject *
1357_asyncio_Future__make_cancelled_error_impl(FutureObj *self)
1358/*[clinic end generated code: output=a5df276f6c1213de input=ac6effe4ba795ecc]*/
1359{
1360 PyObject *exc = create_cancelled_error(self->fut_cancel_msg);
1361 _PyErr_StackItem *exc_state = &self->fut_cancelled_exc_state;
1362 /* Transfer ownership of exc_value from exc_state to exc since we are
1363 done with it. */
1364 PyException_SetContext(exc, exc_state->exc_value);
1365 exc_state->exc_value = NULL;
1366
1367 return exc;
1368}
1369
1370/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001371_asyncio.Future._repr_info
1372[clinic start generated code]*/
1373
1374static PyObject *
1375_asyncio_Future__repr_info_impl(FutureObj *self)
1376/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001377{
Petr Viktorinffd97532020-02-11 17:46:57 +01001378 return PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001379}
1380
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001381static PyObject *
1382FutureObj_repr(FutureObj *fut)
1383{
1384 _Py_IDENTIFIER(_repr_info);
1385
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001386 ENSURE_FUTURE_ALIVE(fut)
1387
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001388 PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
1389 &PyId__repr_info);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001390 if (rinfo == NULL) {
1391 return NULL;
1392 }
1393
Serhiy Storchakabca49392017-09-03 08:10:14 +03001394 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001395 Py_DECREF(rinfo);
1396 if (rinfo_s == NULL) {
1397 return NULL;
1398 }
1399
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001400 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1401 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001402 Py_DECREF(rinfo_s);
1403 return rstr;
1404}
1405
1406static void
1407FutureObj_finalize(FutureObj *fut)
1408{
1409 _Py_IDENTIFIER(call_exception_handler);
1410 _Py_IDENTIFIER(message);
1411 _Py_IDENTIFIER(exception);
1412 _Py_IDENTIFIER(future);
1413 _Py_IDENTIFIER(source_traceback);
1414
Serhiy Storchakabca49392017-09-03 08:10:14 +03001415 PyObject *error_type, *error_value, *error_traceback;
1416 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001417 PyObject *message = NULL;
1418 PyObject *func;
1419
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001420 if (!fut->fut_log_tb) {
1421 return;
1422 }
1423 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001424 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001425
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001426 /* Save the current exception, if any. */
1427 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1428
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001429 context = PyDict_New();
1430 if (context == NULL) {
1431 goto finally;
1432 }
1433
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001434 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001435 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001436 if (message == NULL) {
1437 goto finally;
1438 }
1439
1440 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1441 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1442 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1443 goto finally;
1444 }
1445 if (fut->fut_source_tb != NULL) {
1446 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1447 fut->fut_source_tb) < 0) {
1448 goto finally;
1449 }
1450 }
1451
1452 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1453 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01001454 PyObject *res = PyObject_CallOneArg(func, context);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001455 if (res == NULL) {
1456 PyErr_WriteUnraisable(func);
1457 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001458 else {
1459 Py_DECREF(res);
1460 }
1461 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001462 }
1463
1464finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001465 Py_XDECREF(context);
1466 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001467
1468 /* Restore the saved exception. */
1469 PyErr_Restore(error_type, error_value, error_traceback);
1470}
1471
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001472static PyObject *
1473future_cls_getitem(PyObject *cls, PyObject *type)
1474{
1475 Py_INCREF(cls);
1476 return cls;
1477}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001478
1479static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001480 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001481 0, /* am_aiter */
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001482 0, /* am_anext */
1483 0, /* am_send */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001484};
1485
1486static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001487 _ASYNCIO_FUTURE_RESULT_METHODDEF
1488 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1489 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1490 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1491 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1492 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1493 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1494 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1495 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001496 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001497 _ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001498 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001499 {"__class_getitem__", future_cls_getitem, METH_O|METH_CLASS, NULL},
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001500 {NULL, NULL} /* Sentinel */
1501};
1502
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001503#define FUTURE_COMMON_GETSETLIST \
1504 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1505 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1506 (setter)FutureObj_set_blocking, NULL}, \
1507 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1508 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1509 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1510 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001511 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1512 (setter)FutureObj_set_log_traceback, NULL}, \
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001513 {"_source_traceback", (getter)FutureObj_get_source_traceback, \
1514 NULL, NULL}, \
1515 {"_cancel_message", (getter)FutureObj_get_cancel_message, \
1516 (setter)FutureObj_set_cancel_message, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001517
1518static PyGetSetDef FutureType_getsetlist[] = {
1519 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001520 {NULL} /* Sentinel */
1521};
1522
1523static void FutureObj_dealloc(PyObject *self);
1524
1525static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001526 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001527 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001528 sizeof(FutureObj), /* tp_basicsize */
1529 .tp_dealloc = FutureObj_dealloc,
1530 .tp_as_async = &FutureType_as_async,
1531 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001532 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001533 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001534 .tp_traverse = (traverseproc)FutureObj_traverse,
1535 .tp_clear = (inquiry)FutureObj_clear,
1536 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001537 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001538 .tp_methods = FutureType_methods,
1539 .tp_getset = FutureType_getsetlist,
1540 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001541 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001542 .tp_new = PyType_GenericNew,
1543 .tp_finalize = (destructor)FutureObj_finalize,
1544};
1545
1546static void
1547FutureObj_dealloc(PyObject *self)
1548{
1549 FutureObj *fut = (FutureObj *)self;
1550
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001551 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001552 /* When fut is subclass of Future, finalizer is called from
1553 * subtype_dealloc.
1554 */
1555 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1556 // resurrected.
1557 return;
1558 }
1559 }
1560
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001561 PyObject_GC_UnTrack(self);
1562
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001563 if (fut->fut_weakreflist != NULL) {
1564 PyObject_ClearWeakRefs(self);
1565 }
1566
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001567 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001568 Py_TYPE(fut)->tp_free(fut);
1569}
1570
1571
1572/*********************** Future Iterator **************************/
1573
1574typedef struct {
1575 PyObject_HEAD
1576 FutureObj *future;
1577} futureiterobject;
1578
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001579
1580#define FI_FREELIST_MAXLEN 255
1581static futureiterobject *fi_freelist = NULL;
1582static Py_ssize_t fi_freelist_len = 0;
1583
1584
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001585static void
1586FutureIter_dealloc(futureiterobject *it)
1587{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001588 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001589 Py_CLEAR(it->future);
1590
1591 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1592 fi_freelist_len++;
1593 it->future = (FutureObj*) fi_freelist;
1594 fi_freelist = it;
1595 }
1596 else {
1597 PyObject_GC_Del(it);
1598 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001599}
1600
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001601static PySendResult
1602FutureIter_am_send(futureiterobject *it,
1603 PyObject *Py_UNUSED(arg),
1604 PyObject **result)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001605{
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001606 /* arg is unused, see the comment on FutureIter_send for clarification */
1607
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001608 PyObject *res;
1609 FutureObj *fut = it->future;
1610
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001611 *result = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001612 if (fut == NULL) {
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001613 return PYGEN_ERROR;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001614 }
1615
1616 if (fut->fut_state == STATE_PENDING) {
1617 if (!fut->fut_blocking) {
1618 fut->fut_blocking = 1;
1619 Py_INCREF(fut);
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001620 *result = (PyObject *)fut;
1621 return PYGEN_NEXT;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001622 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001623 PyErr_SetString(PyExc_RuntimeError,
1624 "await wasn't used with future");
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001625 return PYGEN_ERROR;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001626 }
1627
Serhiy Storchakabca49392017-09-03 08:10:14 +03001628 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001629 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001630 if (res != NULL) {
Andrew Svetlovcda99b42020-11-11 17:48:53 +02001631 Py_DECREF(fut);
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001632 *result = res;
1633 return PYGEN_RETURN;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001634 }
1635
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001636 Py_DECREF(fut);
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001637 return PYGEN_ERROR;
1638}
1639
1640static PyObject *
1641FutureIter_iternext(futureiterobject *it)
1642{
1643 PyObject *result;
1644 switch (FutureIter_am_send(it, Py_None, &result)) {
1645 case PYGEN_RETURN:
1646 (void)_PyGen_SetStopIterationValue(result);
1647 Py_DECREF(result);
1648 return NULL;
1649 case PYGEN_NEXT:
1650 return result;
1651 case PYGEN_ERROR:
1652 return NULL;
1653 default:
1654 Py_UNREACHABLE();
1655 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001656}
1657
1658static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001659FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001660{
INADA Naoki74c17532016-10-25 19:00:45 +09001661 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001662 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001663 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001664 return FutureIter_iternext(self);
1665}
1666
1667static PyObject *
1668FutureIter_throw(futureiterobject *self, PyObject *args)
1669{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001670 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001671 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1672 return NULL;
1673
1674 if (val == Py_None) {
1675 val = NULL;
1676 }
1677 if (tb == Py_None) {
1678 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001679 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1680 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1681 return NULL;
1682 }
1683
1684 Py_INCREF(type);
1685 Py_XINCREF(val);
1686 Py_XINCREF(tb);
1687
1688 if (PyExceptionClass_Check(type)) {
1689 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001690 /* No need to call PyException_SetTraceback since we'll be calling
1691 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001692 } else if (PyExceptionInstance_Check(type)) {
1693 if (val) {
1694 PyErr_SetString(PyExc_TypeError,
1695 "instance exception may not have a separate value");
1696 goto fail;
1697 }
1698 val = type;
1699 type = PyExceptionInstance_Class(type);
1700 Py_INCREF(type);
1701 if (tb == NULL)
1702 tb = PyException_GetTraceback(val);
1703 } else {
1704 PyErr_SetString(PyExc_TypeError,
1705 "exceptions must be classes deriving BaseException or "
1706 "instances of such a class");
1707 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001708 }
1709
1710 Py_CLEAR(self->future);
1711
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001712 PyErr_Restore(type, val, tb);
1713
Serhiy Storchakabca49392017-09-03 08:10:14 +03001714 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001715
1716 fail:
1717 Py_DECREF(type);
1718 Py_XDECREF(val);
1719 Py_XDECREF(tb);
1720 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001721}
1722
1723static PyObject *
1724FutureIter_close(futureiterobject *self, PyObject *arg)
1725{
1726 Py_CLEAR(self->future);
1727 Py_RETURN_NONE;
1728}
1729
1730static int
1731FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1732{
1733 Py_VISIT(it->future);
1734 return 0;
1735}
1736
1737static PyMethodDef FutureIter_methods[] = {
1738 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1739 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1740 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1741 {NULL, NULL} /* Sentinel */
1742};
1743
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001744static PyAsyncMethods FutureIterType_as_async = {
1745 0, /* am_await */
1746 0, /* am_aiter */
1747 0, /* am_anext */
1748 (sendfunc)FutureIter_am_send, /* am_send */
1749};
1750
1751
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001752static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001753 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001754 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001755 .tp_basicsize = sizeof(futureiterobject),
1756 .tp_itemsize = 0,
1757 .tp_dealloc = (destructor)FutureIter_dealloc,
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001758 .tp_as_async = &FutureIterType_as_async,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001759 .tp_getattro = PyObject_GenericGetAttr,
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001760 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1761 Py_TPFLAGS_HAVE_AM_SEND,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001762 .tp_traverse = (traverseproc)FutureIter_traverse,
1763 .tp_iter = PyObject_SelfIter,
1764 .tp_iternext = (iternextfunc)FutureIter_iternext,
1765 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001766};
1767
1768static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001769future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001770{
1771 futureiterobject *it;
1772
1773 if (!PyObject_TypeCheck(fut, &FutureType)) {
1774 PyErr_BadInternalCall();
1775 return NULL;
1776 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001777
1778 ENSURE_FUTURE_ALIVE(fut)
1779
1780 if (fi_freelist_len) {
1781 fi_freelist_len--;
1782 it = fi_freelist;
1783 fi_freelist = (futureiterobject*) it->future;
1784 it->future = NULL;
1785 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001786 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001787 else {
1788 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1789 if (it == NULL) {
1790 return NULL;
1791 }
1792 }
1793
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001794 Py_INCREF(fut);
1795 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001796 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001797 return (PyObject*)it;
1798}
1799
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001800
1801/*********************** Task **************************/
1802
1803
1804/*[clinic input]
1805class _asyncio.Task "TaskObj *" "&Task_Type"
1806[clinic start generated code]*/
1807/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1808
1809static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001810static PyObject * task_wakeup(TaskObj *, PyObject *);
1811static PyObject * task_step(TaskObj *, PyObject *);
1812
1813/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001814
INADA Naokic411a7d2016-10-18 11:48:14 +09001815static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001816TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001817{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001818 Py_CLEAR(o->sw_task);
1819 Py_CLEAR(o->sw_arg);
1820 return 0;
1821}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001822
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001823static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001824TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001825{
1826 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001827 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001828 Py_TYPE(o)->tp_free(o);
1829}
1830
1831static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001832TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001833 PyObject *args, PyObject *kwds)
1834{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001835 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1836 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1837 return NULL;
1838 }
1839 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1840 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1841 return NULL;
1842 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001843 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001844}
1845
1846static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001847TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001848 visitproc visit, void *arg)
1849{
1850 Py_VISIT(o->sw_task);
1851 Py_VISIT(o->sw_arg);
1852 return 0;
1853}
1854
1855static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001856TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001857{
1858 if (o->sw_task) {
1859 Py_INCREF(o->sw_task);
1860 return (PyObject*)o->sw_task;
1861 }
1862 Py_RETURN_NONE;
1863}
1864
Serhiy Storchakabca49392017-09-03 08:10:14 +03001865static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1866 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001867 {NULL} /* Sentinel */
1868};
1869
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001870static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001871 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001872 "TaskStepMethWrapper",
1873 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001874 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001875 .tp_getset = TaskStepMethWrapper_getsetlist,
1876 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1877 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001878 .tp_getattro = PyObject_GenericGetAttr,
1879 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001880 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1881 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001882};
1883
1884static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001885TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001886{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001887 TaskStepMethWrapper *o;
1888 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001889 if (o == NULL) {
1890 return NULL;
1891 }
1892
1893 Py_INCREF(task);
1894 o->sw_task = task;
1895
1896 Py_XINCREF(arg);
1897 o->sw_arg = arg;
1898
1899 PyObject_GC_Track(o);
1900 return (PyObject*) o;
1901}
1902
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07001903/* ----- Task._wakeup implementation */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001904
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07001905static PyMethodDef TaskWakeupDef = {
1906 "task_wakeup",
1907 (PyCFunction)task_wakeup,
1908 METH_O,
1909 NULL
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001910};
1911
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001912/* ----- Task introspection helpers */
1913
1914static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001915register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001916{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001917 _Py_IDENTIFIER(add);
1918
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001919 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1920 &PyId_add, task);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001921 if (res == NULL) {
1922 return -1;
1923 }
1924 Py_DECREF(res);
1925 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001926}
1927
1928
1929static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001930unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001931{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001932 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001933
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001934 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1935 &PyId_discard, task);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001936 if (res == NULL) {
1937 return -1;
1938 }
1939 Py_DECREF(res);
1940 return 0;
1941}
1942
1943
1944static int
1945enter_task(PyObject *loop, PyObject *task)
1946{
1947 PyObject *item;
1948 Py_hash_t hash;
1949 hash = PyObject_Hash(loop);
1950 if (hash == -1) {
1951 return -1;
1952 }
1953 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1954 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001955 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001956 PyErr_Format(
1957 PyExc_RuntimeError,
1958 "Cannot enter into task %R while another " \
1959 "task %R is being executed.",
1960 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001961 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001962 return -1;
1963 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001964 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001965 return -1;
1966 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001967 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001968}
1969
1970
1971static int
1972leave_task(PyObject *loop, PyObject *task)
1973/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1974{
1975 PyObject *item;
1976 Py_hash_t hash;
1977 hash = PyObject_Hash(loop);
1978 if (hash == -1) {
1979 return -1;
1980 }
1981 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1982 if (item != task) {
1983 if (item == NULL) {
1984 /* Not entered, replace with None */
1985 item = Py_None;
1986 }
1987 PyErr_Format(
1988 PyExc_RuntimeError,
1989 "Leaving task %R does not match the current task %R.",
1990 task, item, NULL);
1991 return -1;
1992 }
1993 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
1994}
1995
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001996/* ----- Task */
1997
1998/*[clinic input]
1999_asyncio.Task.__init__
2000
Serhiy Storchakabca49392017-09-03 08:10:14 +03002001 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002002 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002003 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002004 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002005
2006A coroutine wrapped in a Future.
2007[clinic start generated code]*/
2008
2009static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002010_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2011 PyObject *name)
2012/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002013{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002014 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002015 return -1;
2016 }
INADA Naokic411a7d2016-10-18 11:48:14 +09002017
Yury Selivanova9d7e552017-12-19 07:18:45 -05002018 int is_coro = is_coroutine(coro);
2019 if (is_coro == -1) {
2020 return -1;
2021 }
2022 if (is_coro == 0) {
2023 self->task_log_destroy_pending = 0;
2024 PyErr_Format(PyExc_TypeError,
2025 "a coroutine was expected, got %R",
2026 coro, NULL);
2027 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02002028 }
2029
Oren Milmand019bc82018-02-13 12:28:33 +02002030 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05002031 if (self->task_context == NULL) {
2032 return -1;
2033 }
2034
Oren Milmand019bc82018-02-13 12:28:33 +02002035 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002036 self->task_must_cancel = 0;
2037 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002038 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02002039 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002040
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002041 if (name == Py_None) {
2042 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03002043 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002044 name = PyObject_Str(name);
2045 } else {
2046 Py_INCREF(name);
2047 }
2048 Py_XSETREF(self->task_name, name);
2049 if (self->task_name == NULL) {
2050 return -1;
2051 }
2052
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002053 if (task_call_step_soon(self, NULL)) {
2054 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09002055 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002056 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002057}
2058
2059static int
2060TaskObj_clear(TaskObj *task)
2061{
2062 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002063 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002064 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002065 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002066 Py_CLEAR(task->task_fut_waiter);
2067 return 0;
2068}
2069
2070static int
2071TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2072{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002073 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002074 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002075 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002076 Py_VISIT(task->task_fut_waiter);
2077 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2078 return 0;
2079}
2080
2081static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002082TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002083{
2084 if (task->task_log_destroy_pending) {
2085 Py_RETURN_TRUE;
2086 }
2087 else {
2088 Py_RETURN_FALSE;
2089 }
2090}
2091
2092static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002093TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002094{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002095 if (val == NULL) {
2096 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2097 return -1;
2098 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002099 int is_true = PyObject_IsTrue(val);
2100 if (is_true < 0) {
2101 return -1;
2102 }
2103 task->task_log_destroy_pending = is_true;
2104 return 0;
2105}
2106
2107static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002108TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002109{
2110 if (task->task_must_cancel) {
2111 Py_RETURN_TRUE;
2112 }
2113 else {
2114 Py_RETURN_FALSE;
2115 }
2116}
2117
2118static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002119TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002120{
2121 if (task->task_coro) {
2122 Py_INCREF(task->task_coro);
2123 return task->task_coro;
2124 }
2125
2126 Py_RETURN_NONE;
2127}
2128
2129static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002130TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002131{
2132 if (task->task_fut_waiter) {
2133 Py_INCREF(task->task_fut_waiter);
2134 return task->task_fut_waiter;
2135 }
2136
2137 Py_RETURN_NONE;
2138}
2139
2140/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002141_asyncio.Task._make_cancelled_error
2142
2143Create the CancelledError to raise if the Task is cancelled.
2144
2145This should only be called once when handling a cancellation since
2146it erases the context exception value.
2147[clinic start generated code]*/
2148
2149static PyObject *
2150_asyncio_Task__make_cancelled_error_impl(TaskObj *self)
2151/*[clinic end generated code: output=55a819e8b4276fab input=52c0e32de8e2f840]*/
2152{
2153 FutureObj *fut = (FutureObj*)self;
2154 return _asyncio_Future__make_cancelled_error_impl(fut);
2155}
2156
2157
2158/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002159_asyncio.Task._repr_info
2160[clinic start generated code]*/
2161
2162static PyObject *
2163_asyncio_Task__repr_info_impl(TaskObj *self)
2164/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2165{
Petr Viktorinffd97532020-02-11 17:46:57 +01002166 return PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002167}
2168
2169/*[clinic input]
2170_asyncio.Task.cancel
2171
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002172 msg: object = None
2173
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002174Request that this task cancel itself.
2175
2176This arranges for a CancelledError to be thrown into the
2177wrapped coroutine on the next cycle through the event loop.
2178The coroutine then has a chance to clean up or even deny
2179the request using try/except/finally.
2180
2181Unlike Future.cancel, this does not guarantee that the
2182task will be cancelled: the exception might be caught and
2183acted upon, delaying cancellation of the task or preventing
2184cancellation completely. The task may also return a value or
2185raise a different exception.
2186
2187Immediately after this method is called, Task.cancelled() will
2188not return True (unless the task was already cancelled). A
2189task will be marked as cancelled when the wrapped coroutine
2190terminates with a CancelledError exception (even if cancel()
2191was not called).
2192[clinic start generated code]*/
2193
2194static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002195_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
2196/*[clinic end generated code: output=c66b60d41c74f9f1 input=f4ff8e8ffc5f1c00]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002197{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002198 self->task_log_tb = 0;
2199
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002200 if (self->task_state != STATE_PENDING) {
2201 Py_RETURN_FALSE;
2202 }
2203
2204 if (self->task_fut_waiter) {
2205 PyObject *res;
2206 int is_true;
2207
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002208 res = _PyObject_CallMethodIdOneArg(self->task_fut_waiter,
2209 &PyId_cancel, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002210 if (res == NULL) {
2211 return NULL;
2212 }
2213
2214 is_true = PyObject_IsTrue(res);
2215 Py_DECREF(res);
2216 if (is_true < 0) {
2217 return NULL;
2218 }
2219
2220 if (is_true) {
2221 Py_RETURN_TRUE;
2222 }
2223 }
2224
2225 self->task_must_cancel = 1;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002226 Py_XINCREF(msg);
2227 Py_XSETREF(self->task_cancel_msg, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002228 Py_RETURN_TRUE;
2229}
2230
2231/*[clinic input]
2232_asyncio.Task.get_stack
2233
2234 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002235 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002236
2237Return the list of stack frames for this task's coroutine.
2238
2239If the coroutine is not done, this returns the stack where it is
2240suspended. If the coroutine has completed successfully or was
2241cancelled, this returns an empty list. If the coroutine was
2242terminated by an exception, this returns the list of traceback
2243frames.
2244
2245The frames are always ordered from oldest to newest.
2246
2247The optional limit gives the maximum number of frames to
2248return; by default all available frames are returned. Its
2249meaning differs depending on whether a stack or a traceback is
2250returned: the newest frames of a stack are returned, but the
2251oldest frames of a traceback are returned. (This matches the
2252behavior of the traceback module.)
2253
2254For reasons beyond our control, only one stack frame is
2255returned for a suspended coroutine.
2256[clinic start generated code]*/
2257
2258static PyObject *
2259_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002260/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002261{
2262 return PyObject_CallFunctionObjArgs(
2263 asyncio_task_get_stack_func, self, limit, NULL);
2264}
2265
2266/*[clinic input]
2267_asyncio.Task.print_stack
2268
2269 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002270 limit: object = None
2271 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002272
2273Print the stack or traceback for this task's coroutine.
2274
2275This produces output similar to that of the traceback module,
2276for the frames retrieved by get_stack(). The limit argument
2277is passed to get_stack(). The file argument is an I/O stream
2278to which the output is written; by default output is written
2279to sys.stderr.
2280[clinic start generated code]*/
2281
2282static PyObject *
2283_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2284 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002285/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002286{
2287 return PyObject_CallFunctionObjArgs(
2288 asyncio_task_print_stack_func, self, limit, file, NULL);
2289}
2290
2291/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002292_asyncio.Task.set_result
2293
2294 result: object
2295 /
2296[clinic start generated code]*/
2297
2298static PyObject *
2299_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2300/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2301{
2302 PyErr_SetString(PyExc_RuntimeError,
2303 "Task does not support set_result operation");
2304 return NULL;
2305}
2306
2307/*[clinic input]
2308_asyncio.Task.set_exception
2309
2310 exception: object
2311 /
2312[clinic start generated code]*/
2313
2314static PyObject *
2315_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2316/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2317{
2318 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002319 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002320 return NULL;
2321}
2322
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002323/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002324_asyncio.Task.get_coro
2325[clinic start generated code]*/
2326
2327static PyObject *
2328_asyncio_Task_get_coro_impl(TaskObj *self)
2329/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2330{
2331 Py_INCREF(self->task_coro);
2332 return self->task_coro;
2333}
2334
2335/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002336_asyncio.Task.get_name
2337[clinic start generated code]*/
2338
2339static PyObject *
2340_asyncio_Task_get_name_impl(TaskObj *self)
2341/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2342{
2343 if (self->task_name) {
2344 Py_INCREF(self->task_name);
2345 return self->task_name;
2346 }
2347
2348 Py_RETURN_NONE;
2349}
2350
2351/*[clinic input]
2352_asyncio.Task.set_name
2353
2354 value: object
2355 /
2356[clinic start generated code]*/
2357
2358static PyObject *
2359_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2360/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2361{
Alex Grönholma7548232018-08-09 23:49:49 +03002362 if (!PyUnicode_CheckExact(value)) {
2363 value = PyObject_Str(value);
2364 if (value == NULL) {
2365 return NULL;
2366 }
2367 } else {
2368 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002369 }
2370
Alex Grönholma7548232018-08-09 23:49:49 +03002371 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002372 Py_RETURN_NONE;
2373}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002374
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002375static void
2376TaskObj_finalize(TaskObj *task)
2377{
2378 _Py_IDENTIFIER(call_exception_handler);
2379 _Py_IDENTIFIER(task);
2380 _Py_IDENTIFIER(message);
2381 _Py_IDENTIFIER(source_traceback);
2382
Serhiy Storchakabca49392017-09-03 08:10:14 +03002383 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002384 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002385 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002386 PyObject *error_type, *error_value, *error_traceback;
2387
2388 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2389 goto done;
2390 }
2391
2392 /* Save the current exception, if any. */
2393 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2394
2395 context = PyDict_New();
2396 if (context == NULL) {
2397 goto finally;
2398 }
2399
2400 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2401 if (message == NULL) {
2402 goto finally;
2403 }
2404
2405 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2406 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2407 {
2408 goto finally;
2409 }
2410
2411 if (task->task_source_tb != NULL) {
2412 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2413 task->task_source_tb) < 0)
2414 {
2415 goto finally;
2416 }
2417 }
2418
2419 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2420 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01002421 PyObject *res = PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002422 if (res == NULL) {
2423 PyErr_WriteUnraisable(func);
2424 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002425 else {
2426 Py_DECREF(res);
2427 }
2428 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002429 }
2430
2431finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002432 Py_XDECREF(context);
2433 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002434
2435 /* Restore the saved exception. */
2436 PyErr_Restore(error_type, error_value, error_traceback);
2437
2438done:
2439 FutureObj_finalize((FutureObj*)task);
2440}
2441
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002442static PyObject *
2443task_cls_getitem(PyObject *cls, PyObject *type)
2444{
2445 Py_INCREF(cls);
2446 return cls;
2447}
2448
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002449static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2450
2451static PyMethodDef TaskType_methods[] = {
2452 _ASYNCIO_FUTURE_RESULT_METHODDEF
2453 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002454 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2455 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2456 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2457 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002458 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2459 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002460 _ASYNCIO_TASK_CANCEL_METHODDEF
2461 _ASYNCIO_TASK_GET_STACK_METHODDEF
2462 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002463 _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002464 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002465 _ASYNCIO_TASK_GET_NAME_METHODDEF
2466 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002467 _ASYNCIO_TASK_GET_CORO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002468 {"__class_getitem__", task_cls_getitem, METH_O|METH_CLASS, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002469 {NULL, NULL} /* Sentinel */
2470};
2471
2472static PyGetSetDef TaskType_getsetlist[] = {
2473 FUTURE_COMMON_GETSETLIST
2474 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2475 (setter)TaskObj_set_log_destroy_pending, NULL},
2476 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2477 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2478 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2479 {NULL} /* Sentinel */
2480};
2481
2482static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002483 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002484 "_asyncio.Task",
2485 sizeof(TaskObj), /* tp_basicsize */
2486 .tp_base = &FutureType,
2487 .tp_dealloc = TaskObj_dealloc,
2488 .tp_as_async = &FutureType_as_async,
2489 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002490 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002491 .tp_doc = _asyncio_Task___init____doc__,
2492 .tp_traverse = (traverseproc)TaskObj_traverse,
2493 .tp_clear = (inquiry)TaskObj_clear,
2494 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2495 .tp_iter = (getiterfunc)future_new_iter,
2496 .tp_methods = TaskType_methods,
2497 .tp_getset = TaskType_getsetlist,
2498 .tp_dictoffset = offsetof(TaskObj, dict),
2499 .tp_init = (initproc)_asyncio_Task___init__,
2500 .tp_new = PyType_GenericNew,
2501 .tp_finalize = (destructor)TaskObj_finalize,
2502};
2503
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002504static void
2505TaskObj_dealloc(PyObject *self)
2506{
2507 TaskObj *task = (TaskObj *)self;
2508
2509 if (Task_CheckExact(self)) {
2510 /* When fut is subclass of Task, finalizer is called from
2511 * subtype_dealloc.
2512 */
2513 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2514 // resurrected.
2515 return;
2516 }
2517 }
2518
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002519 PyObject_GC_UnTrack(self);
2520
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002521 if (task->task_weakreflist != NULL) {
2522 PyObject_ClearWeakRefs(self);
2523 }
2524
2525 (void)TaskObj_clear(task);
2526 Py_TYPE(task)->tp_free(task);
2527}
2528
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002529static int
2530task_call_step_soon(TaskObj *task, PyObject *arg)
2531{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002532 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002533 if (cb == NULL) {
2534 return -1;
2535 }
2536
Yury Selivanovf23746a2018-01-22 19:11:18 -05002537 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002538 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002539 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002540}
2541
2542static PyObject *
2543task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2544{
2545 PyObject* msg;
2546
2547 va_list vargs;
2548#ifdef HAVE_STDARG_PROTOTYPES
2549 va_start(vargs, format);
2550#else
2551 va_start(vargs);
2552#endif
2553 msg = PyUnicode_FromFormatV(format, vargs);
2554 va_end(vargs);
2555
2556 if (msg == NULL) {
2557 return NULL;
2558 }
2559
Petr Viktorinffd97532020-02-11 17:46:57 +01002560 PyObject *e = PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002561 Py_DECREF(msg);
2562 if (e == NULL) {
2563 return NULL;
2564 }
2565
2566 if (task_call_step_soon(task, e) == -1) {
2567 Py_DECREF(e);
2568 return NULL;
2569 }
2570
2571 Py_DECREF(e);
2572 Py_RETURN_NONE;
2573}
2574
Vladimir Matveev2b053612020-09-18 18:38:38 -07002575static inline int
2576gen_status_from_result(PyObject **result)
2577{
2578 if (*result != NULL) {
2579 return PYGEN_NEXT;
2580 }
2581 if (_PyGen_FetchStopIterationValue(result) == 0) {
2582 return PYGEN_RETURN;
2583 }
2584
2585 assert(PyErr_Occurred());
2586 return PYGEN_ERROR;
2587}
2588
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002589static 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 */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002624 exc = create_cancelled_error(task->task_cancel_msg);
2625
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002626 if (!exc) {
2627 goto fail;
2628 }
2629 clear_exc = 1;
2630 }
2631
2632 task->task_must_cancel = 0;
2633 }
2634
2635 Py_CLEAR(task->task_fut_waiter);
2636
Serhiy Storchakabca49392017-09-03 08:10:14 +03002637 coro = task->task_coro;
2638 if (coro == NULL) {
2639 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
Chris Jerdonekd2c349b2020-05-08 03:54:38 -07002640 if (clear_exc) {
2641 /* We created 'exc' during this call */
2642 Py_DECREF(exc);
2643 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002644 return NULL;
2645 }
2646
Vladimir Matveev2b053612020-09-18 18:38:38 -07002647 int gen_status = PYGEN_ERROR;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002648 if (exc == NULL) {
Vladimir Matveev037245c2020-10-09 17:15:15 -07002649 gen_status = PyIter_Send(coro, Py_None, &result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002650 }
2651 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002652 result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
Vladimir Matveev2b053612020-09-18 18:38:38 -07002653 gen_status = gen_status_from_result(&result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002654 if (clear_exc) {
2655 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002656 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002657 }
2658 }
2659
Vladimir Matveev2b053612020-09-18 18:38:38 -07002660 if (gen_status == PYGEN_RETURN || gen_status == PYGEN_ERROR) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002661 PyObject *et, *ev, *tb;
2662
Vladimir Matveev2b053612020-09-18 18:38:38 -07002663 if (result != NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002664 /* The error is StopIteration and that means that
2665 the underlying coroutine has resolved */
Yury Selivanovedad4d82019-09-25 03:32:08 -07002666
2667 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002668 if (task->task_must_cancel) {
2669 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002670 task->task_must_cancel = 0;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002671 res = future_cancel((FutureObj*)task, task->task_cancel_msg);
INADA Naoki991adca2017-05-11 21:18:38 +09002672 }
Yury Selivanovedad4d82019-09-25 03:32:08 -07002673 else {
Vladimir Matveev2b053612020-09-18 18:38:38 -07002674 res = future_set_result((FutureObj*)task, result);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002675 }
2676
Vladimir Matveev2b053612020-09-18 18:38:38 -07002677 Py_DECREF(result);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002678
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002679 if (res == NULL) {
2680 return NULL;
2681 }
2682 Py_DECREF(res);
2683 Py_RETURN_NONE;
2684 }
2685
2686 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2687 /* CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002688 PyErr_Fetch(&et, &ev, &tb);
2689
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002690 FutureObj *fut = (FutureObj*)task;
2691 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
2692 exc_state->exc_type = et;
2693 exc_state->exc_value = ev;
2694 exc_state->exc_traceback = tb;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002695
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002696 return future_cancel(fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002697 }
2698
2699 /* Some other exception; pop it and call Task.set_exception() */
2700 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002701
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002702 assert(et);
2703 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2704 PyErr_NormalizeException(&et, &ev, &tb);
2705 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002706 if (tb != NULL) {
2707 PyException_SetTraceback(ev, tb);
2708 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002709 o = future_set_exception((FutureObj*)task, ev);
2710 if (!o) {
2711 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002712 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002713 Py_XDECREF(tb);
2714 Py_XDECREF(ev);
2715 goto fail;
2716 }
2717 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002718 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002719
Yury Selivanov431b5402019-05-27 14:45:12 +02002720 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2721 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2722 {
2723 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002724 PyErr_Restore(et, ev, tb);
2725 goto fail;
2726 }
2727
Serhiy Storchakabca49392017-09-03 08:10:14 +03002728 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002729 Py_XDECREF(tb);
2730 Py_XDECREF(ev);
2731
2732 Py_RETURN_NONE;
2733 }
2734
2735 if (result == (PyObject*)task) {
2736 /* We have a task that wants to await on itself */
2737 goto self_await;
2738 }
2739
2740 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2741 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2742 PyObject *wrapper;
2743 PyObject *res;
2744 FutureObj *fut = (FutureObj*)result;
2745
2746 /* Check if `result` future is attached to a different loop */
2747 if (fut->fut_loop != task->task_loop) {
2748 goto different_loop;
2749 }
2750
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002751 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002752 goto yield_insteadof_yf;
2753 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002754
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002755 fut->fut_blocking = 0;
2756
2757 /* result.add_done_callback(task._wakeup) */
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07002758 wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002759 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002760 goto fail;
2761 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002762 res = future_add_done_callback(
2763 (FutureObj*)result, wrapper, task->task_context);
2764 Py_DECREF(wrapper);
2765 if (res == NULL) {
2766 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002767 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002768 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002769
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002770 /* task._fut_waiter = result */
2771 task->task_fut_waiter = result; /* no incref is necessary */
2772
2773 if (task->task_must_cancel) {
2774 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002775 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002776 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2777 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002778 if (r == NULL) {
2779 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002780 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002781 is_true = PyObject_IsTrue(r);
2782 Py_DECREF(r);
2783 if (is_true < 0) {
2784 return NULL;
2785 }
2786 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002787 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002788 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002789 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002790
2791 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002792 }
2793
2794 /* Check if `result` is None */
2795 if (result == Py_None) {
2796 /* Bare yield relinquishes control for one event loop iteration. */
2797 if (task_call_step_soon(task, NULL)) {
2798 goto fail;
2799 }
2800 return result;
2801 }
2802
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002803 /* Check if `result` is a Future-compatible object */
2804 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2805 goto fail;
2806 }
2807 if (o != NULL && o != Py_None) {
2808 /* `result` is a Future-compatible object */
2809 PyObject *wrapper;
2810 PyObject *res;
2811
2812 int blocking = PyObject_IsTrue(o);
2813 Py_DECREF(o);
2814 if (blocking < 0) {
2815 goto fail;
2816 }
2817
2818 /* Check if `result` future is attached to a different loop */
2819 PyObject *oloop = get_future_loop(result);
2820 if (oloop == NULL) {
2821 goto fail;
2822 }
2823 if (oloop != task->task_loop) {
2824 Py_DECREF(oloop);
2825 goto different_loop;
2826 }
2827 Py_DECREF(oloop);
2828
2829 if (!blocking) {
2830 goto yield_insteadof_yf;
2831 }
2832
2833 /* result._asyncio_future_blocking = False */
2834 if (_PyObject_SetAttrId(
2835 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2836 goto fail;
2837 }
2838
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07002839 wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002840 if (wrapper == NULL) {
2841 goto fail;
2842 }
2843
2844 /* result.add_done_callback(task._wakeup) */
2845 PyObject *add_cb = _PyObject_GetAttrId(
2846 result, &PyId_add_done_callback);
2847 if (add_cb == NULL) {
2848 Py_DECREF(wrapper);
2849 goto fail;
2850 }
2851 PyObject *stack[2];
2852 stack[0] = wrapper;
2853 stack[1] = (PyObject *)task->task_context;
Petr Viktorinffd97532020-02-11 17:46:57 +01002854 res = PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002855 Py_DECREF(add_cb);
2856 Py_DECREF(wrapper);
2857 if (res == NULL) {
2858 goto fail;
2859 }
2860 Py_DECREF(res);
2861
2862 /* task._fut_waiter = result */
2863 task->task_fut_waiter = result; /* no incref is necessary */
2864
2865 if (task->task_must_cancel) {
2866 PyObject *r;
2867 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002868 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2869 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002870 if (r == NULL) {
2871 return NULL;
2872 }
2873 is_true = PyObject_IsTrue(r);
2874 Py_DECREF(r);
2875 if (is_true < 0) {
2876 return NULL;
2877 }
2878 else if (is_true) {
2879 task->task_must_cancel = 0;
2880 }
2881 }
2882
2883 Py_RETURN_NONE;
2884 }
2885
2886 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002887 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002888 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2889 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002890 goto fail;
2891 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002892 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002893 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002894 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002895 task, PyExc_RuntimeError,
2896 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002897 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002898 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002899 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002900 }
2901
2902 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002903 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002904 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002905 Py_DECREF(result);
2906 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002907
2908self_await:
2909 o = task_set_error_soon(
2910 task, PyExc_RuntimeError,
2911 "Task cannot await on itself: %R", task);
2912 Py_DECREF(result);
2913 return o;
2914
2915yield_insteadof_yf:
2916 o = task_set_error_soon(
2917 task, PyExc_RuntimeError,
2918 "yield was used instead of yield from "
2919 "in task %R with %R",
2920 task, result);
2921 Py_DECREF(result);
2922 return o;
2923
2924different_loop:
2925 o = task_set_error_soon(
2926 task, PyExc_RuntimeError,
2927 "Task %R got Future %R attached to a different loop",
2928 task, result);
2929 Py_DECREF(result);
2930 return o;
2931
2932fail:
2933 Py_XDECREF(result);
2934 return NULL;
2935}
2936
2937static PyObject *
2938task_step(TaskObj *task, PyObject *exc)
2939{
2940 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002941
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002942 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002943 return NULL;
2944 }
2945
2946 res = task_step_impl(task, exc);
2947
2948 if (res == NULL) {
2949 PyObject *et, *ev, *tb;
2950 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002951 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002952 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002953 return NULL;
2954 }
2955 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002956 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002957 Py_DECREF(res);
2958 return NULL;
2959 }
2960 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002961 return res;
2962 }
2963 }
2964}
2965
2966static PyObject *
2967task_wakeup(TaskObj *task, PyObject *o)
2968{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002969 PyObject *et, *ev, *tb;
2970 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002971 assert(o);
2972
2973 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2974 PyObject *fut_result = NULL;
2975 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002976
2977 switch(res) {
2978 case -1:
2979 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002980 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002981 case 0:
2982 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002983 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002984 default:
2985 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002986 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002987 Py_DECREF(fut_result);
2988 return result;
2989 }
2990 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002991 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002992 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2993 if (fut_result != NULL) {
2994 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002995 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002996 }
2997 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002998 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002999
3000 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003001 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
3002 PyErr_NormalizeException(&et, &ev, &tb);
3003 }
3004
Yury Selivanov22feeb82018-01-24 11:31:01 -05003005 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003006
3007 Py_DECREF(et);
3008 Py_XDECREF(tb);
3009 Py_XDECREF(ev);
3010
3011 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003012}
3013
3014
Yury Selivanova70232f2017-12-13 14:49:42 -05003015/*********************** Functions **************************/
3016
3017
3018/*[clinic input]
3019_asyncio._get_running_loop
3020
3021Return the running event loop or None.
3022
3023This is a low-level function intended to be used by event loops.
3024This function is thread-specific.
3025
3026[clinic start generated code]*/
3027
3028static PyObject *
3029_asyncio__get_running_loop_impl(PyObject *module)
3030/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3031{
3032 PyObject *loop;
3033 if (get_running_loop(&loop)) {
3034 return NULL;
3035 }
3036 if (loop == NULL) {
3037 /* There's no currently running event loop */
3038 Py_RETURN_NONE;
3039 }
3040 return loop;
3041}
3042
3043/*[clinic input]
3044_asyncio._set_running_loop
3045 loop: 'O'
3046 /
3047
3048Set the running event loop.
3049
3050This is a low-level function intended to be used by event loops.
3051This function is thread-specific.
3052[clinic start generated code]*/
3053
3054static PyObject *
3055_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3056/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3057{
3058 if (set_running_loop(loop)) {
3059 return NULL;
3060 }
3061 Py_RETURN_NONE;
3062}
3063
3064/*[clinic input]
3065_asyncio.get_event_loop
3066
3067Return an asyncio event loop.
3068
3069When called from a coroutine or a callback (e.g. scheduled with
3070call_soon or similar API), this function will always return the
3071running event loop.
3072
3073If there is no running event loop set, the function will return
3074the result of `get_event_loop_policy().get_event_loop()` call.
3075[clinic start generated code]*/
3076
3077static PyObject *
3078_asyncio_get_event_loop_impl(PyObject *module)
3079/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3080{
3081 return get_event_loop();
3082}
3083
3084/*[clinic input]
3085_asyncio.get_running_loop
3086
3087Return the running event loop. Raise a RuntimeError if there is none.
3088
3089This function is thread-specific.
3090[clinic start generated code]*/
3091
3092static PyObject *
3093_asyncio_get_running_loop_impl(PyObject *module)
3094/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3095{
3096 PyObject *loop;
3097 if (get_running_loop(&loop)) {
3098 return NULL;
3099 }
3100 if (loop == NULL) {
3101 /* There's no currently running event loop */
3102 PyErr_SetString(
3103 PyExc_RuntimeError, "no running event loop");
3104 }
3105 return loop;
3106}
3107
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003108/*[clinic input]
3109_asyncio._register_task
3110
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003111 task: object
3112
3113Register a new task in asyncio as executed by loop.
3114
3115Returns None.
3116[clinic start generated code]*/
3117
3118static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003119_asyncio__register_task_impl(PyObject *module, PyObject *task)
3120/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003121{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003122 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003123 return NULL;
3124 }
3125 Py_RETURN_NONE;
3126}
3127
3128
3129/*[clinic input]
3130_asyncio._unregister_task
3131
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003132 task: object
3133
3134Unregister a task.
3135
3136Returns None.
3137[clinic start generated code]*/
3138
3139static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003140_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3141/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003142{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003143 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003144 return NULL;
3145 }
3146 Py_RETURN_NONE;
3147}
3148
3149
3150/*[clinic input]
3151_asyncio._enter_task
3152
3153 loop: object
3154 task: object
3155
3156Enter into task execution or resume suspended task.
3157
3158Task belongs to loop.
3159
3160Returns None.
3161[clinic start generated code]*/
3162
3163static PyObject *
3164_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3165/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3166{
3167 if (enter_task(loop, task) < 0) {
3168 return NULL;
3169 }
3170 Py_RETURN_NONE;
3171}
3172
3173
3174/*[clinic input]
3175_asyncio._leave_task
3176
3177 loop: object
3178 task: object
3179
3180Leave task execution or suspend a task.
3181
3182Task belongs to loop.
3183
3184Returns None.
3185[clinic start generated code]*/
3186
3187static PyObject *
3188_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3189/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3190{
3191 if (leave_task(loop, task) < 0) {
3192 return NULL;
3193 }
3194 Py_RETURN_NONE;
3195}
3196
Yury Selivanova70232f2017-12-13 14:49:42 -05003197
Yury Selivanov9d411c12018-01-23 15:10:03 -05003198/*********************** PyRunningLoopHolder ********************/
3199
3200
3201static PyRunningLoopHolder *
3202new_running_loop_holder(PyObject *loop)
3203{
3204 PyRunningLoopHolder *rl = PyObject_New(
3205 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3206 if (rl == NULL) {
3207 return NULL;
3208 }
3209
3210#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3211 rl->rl_pid = getpid();
3212#endif
3213
3214 Py_INCREF(loop);
3215 rl->rl_loop = loop;
3216
3217 return rl;
3218}
3219
3220
3221static void
3222PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3223{
3224 Py_CLEAR(rl->rl_loop);
3225 PyObject_Free(rl);
3226}
3227
3228
3229static PyTypeObject PyRunningLoopHolder_Type = {
3230 PyVarObject_HEAD_INIT(NULL, 0)
3231 "_RunningLoopHolder",
3232 sizeof(PyRunningLoopHolder),
3233 .tp_getattro = PyObject_GenericGetAttr,
3234 .tp_flags = Py_TPFLAGS_DEFAULT,
3235 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3236};
3237
3238
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003239/*********************** Module **************************/
3240
3241
3242static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003243module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003244{
3245 PyObject *next;
3246 PyObject *current;
3247
3248 next = (PyObject*) fi_freelist;
3249 while (next != NULL) {
3250 assert(fi_freelist_len > 0);
3251 fi_freelist_len--;
3252
3253 current = next;
3254 next = (PyObject*) ((futureiterobject*) current)->future;
3255 PyObject_GC_Del(current);
3256 }
3257 assert(fi_freelist_len == 0);
3258 fi_freelist = NULL;
3259}
3260
3261
3262static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003263module_free(void *m)
3264{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003265 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003266 Py_CLEAR(traceback_extract_stack);
3267 Py_CLEAR(asyncio_future_repr_info_func);
3268 Py_CLEAR(asyncio_get_event_loop_policy);
3269 Py_CLEAR(asyncio_iscoroutine_func);
3270 Py_CLEAR(asyncio_task_get_stack_func);
3271 Py_CLEAR(asyncio_task_print_stack_func);
3272 Py_CLEAR(asyncio_task_repr_info_func);
3273 Py_CLEAR(asyncio_InvalidStateError);
3274 Py_CLEAR(asyncio_CancelledError);
3275
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003276 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003277 Py_CLEAR(current_tasks);
3278 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003279
Yury Selivanovf23746a2018-01-22 19:11:18 -05003280 Py_CLEAR(context_kwname);
3281
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003282 module_free_freelists();
Jeffrey Quesnellea75e7302020-04-16 22:09:45 -04003283
3284 module_initialized = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003285}
3286
3287static int
3288module_init(void)
3289{
3290 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003291
3292 asyncio_mod = PyImport_ImportModule("asyncio");
3293 if (asyncio_mod == NULL) {
3294 goto fail;
3295 }
Ben Harper321def82019-10-07 12:19:58 -04003296 if (module_initialized != 0) {
3297 return 0;
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02003298 }
Ben Harper321def82019-10-07 12:19:58 -04003299 else {
3300 module_initialized = 1;
3301 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003302
3303 current_tasks = PyDict_New();
3304 if (current_tasks == NULL) {
3305 goto fail;
3306 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003307
Yury Selivanova9d7e552017-12-19 07:18:45 -05003308 iscoroutine_typecache = PySet_New(NULL);
3309 if (iscoroutine_typecache == NULL) {
3310 goto fail;
3311 }
3312
Yury Selivanovf23746a2018-01-22 19:11:18 -05003313
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003314 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003315 if (context_kwname == NULL) {
3316 goto fail;
3317 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003318
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003319#define WITH_MOD(NAME) \
3320 Py_CLEAR(module); \
3321 module = PyImport_ImportModule(NAME); \
3322 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003323 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003324 }
3325
3326#define GET_MOD_ATTR(VAR, NAME) \
3327 VAR = PyObject_GetAttrString(module, NAME); \
3328 if (VAR == NULL) { \
3329 goto fail; \
3330 }
3331
3332 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003333 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003334
3335 WITH_MOD("asyncio.base_futures")
3336 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003337
3338 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003339 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3340 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3341
3342 WITH_MOD("asyncio.base_tasks")
3343 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3344 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3345 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3346
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003347 WITH_MOD("asyncio.coroutines")
3348 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3349
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003350 WITH_MOD("traceback")
3351 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3352
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003353 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003354 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003355 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003356 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003357 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003358 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003359 goto fail;
3360 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003361
Serhiy Storchakabca49392017-09-03 08:10:14 +03003362 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003363 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003364
INADA Naokic411a7d2016-10-18 11:48:14 +09003365fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003366 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003367 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003368 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003369
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003370#undef WITH_MOD
3371#undef GET_MOD_ATTR
3372}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003373
INADA Naokic411a7d2016-10-18 11:48:14 +09003374PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003375
Yury Selivanova70232f2017-12-13 14:49:42 -05003376static PyMethodDef asyncio_methods[] = {
3377 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3378 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3379 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3380 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003381 _ASYNCIO__REGISTER_TASK_METHODDEF
3382 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3383 _ASYNCIO__ENTER_TASK_METHODDEF
3384 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003385 {NULL, NULL}
3386};
3387
INADA Naoki9f2ce252016-10-15 15:39:19 +09003388static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003389 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003390 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003391 module_doc, /* m_doc */
3392 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003393 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003394 NULL, /* m_slots */
3395 NULL, /* m_traverse */
3396 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003397 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003398};
3399
3400
3401PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003402PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003403{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003404 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003405 return NULL;
3406 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003407 if (PyType_Ready(&FutureIterType) < 0) {
3408 return NULL;
3409 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003410 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003411 return NULL;
3412 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003413 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3414 return NULL;
3415 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003416
INADA Naoki9f2ce252016-10-15 15:39:19 +09003417 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003418 if (m == NULL) {
3419 return NULL;
3420 }
3421
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003422 /* FutureType and TaskType are made ready by PyModule_AddType() calls below. */
3423 if (PyModule_AddType(m, &FutureType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003424 Py_DECREF(m);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003425 return NULL;
3426 }
3427
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003428 if (PyModule_AddType(m, &TaskType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003429 Py_DECREF(m);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003430 return NULL;
3431 }
3432
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003433 Py_INCREF(all_tasks);
3434 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3435 Py_DECREF(all_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003436 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003437 return NULL;
3438 }
3439
3440 Py_INCREF(current_tasks);
3441 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3442 Py_DECREF(current_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003443 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003444 return NULL;
3445 }
3446
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003447 return m;
3448}