blob: 56079b0277d1a677165b6ec82a968fbc775cff1b [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 *
Serhiy Storchaka172c0f22021-04-25 13:40:44 +0300322get_event_loop(int stacklevel)
Yury Selivanova70232f2017-12-13 14:49:42 -0500323{
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
Serhiy Storchaka172c0f22021-04-25 13:40:44 +0300334 if (PyErr_WarnEx(PyExc_DeprecationWarning,
335 "There is no current event loop",
336 stacklevel))
337 {
338 return NULL;
339 }
340
Victor Stinner2ff58a22019-06-17 14:27:23 +0200341 policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy);
Yury Selivanova70232f2017-12-13 14:49:42 -0500342 if (policy == NULL) {
343 return NULL;
344 }
345
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200346 loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
Yury Selivanova70232f2017-12-13 14:49:42 -0500347 Py_DECREF(policy);
348 return loop;
349}
350
351
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900352static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400353call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500354{
355 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500356 PyObject *stack[3];
357 Py_ssize_t nargs;
358
359 if (ctx == NULL) {
360 handle = _PyObject_CallMethodIdObjArgs(
361 loop, &PyId_call_soon, func, arg, NULL);
362 }
363 else {
364 /* Use FASTCALL to pass a keyword-only argument to call_soon */
365
366 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
367 if (callable == NULL) {
368 return -1;
369 }
370
371 /* All refs in 'stack' are borrowed. */
372 nargs = 1;
373 stack[0] = func;
374 if (arg != NULL) {
375 stack[1] = arg;
376 nargs++;
377 }
378 stack[nargs] = (PyObject *)ctx;
379
Petr Viktorinffd97532020-02-11 17:46:57 +0100380 handle = PyObject_Vectorcall(callable, stack, nargs, context_kwname);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500381 Py_DECREF(callable);
382 }
383
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500384 if (handle == NULL) {
385 return -1;
386 }
387 Py_DECREF(handle);
388 return 0;
389}
390
391
392static inline int
393future_is_alive(FutureObj *fut)
394{
395 return fut->fut_loop != NULL;
396}
397
398
399static inline int
400future_ensure_alive(FutureObj *fut)
401{
402 if (!future_is_alive(fut)) {
403 PyErr_SetString(PyExc_RuntimeError,
404 "Future object is not initialized.");
405 return -1;
406 }
407 return 0;
408}
409
410
411#define ENSURE_FUTURE_ALIVE(fut) \
412 do { \
413 assert(Future_Check(fut) || Task_Check(fut)); \
414 if (future_ensure_alive((FutureObj*)fut)) { \
415 return NULL; \
416 } \
417 } while(0);
418
419
420static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400421future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900422{
423 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500424 Py_ssize_t i;
425
426 if (fut->fut_callback0 != NULL) {
427 /* There's a 1st callback */
428
429 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500430 fut->fut_loop, fut->fut_callback0,
431 (PyObject *)fut, fut->fut_context0);
432
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500433 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500434 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500435 if (ret) {
436 /* If an error occurs in pure-Python implementation,
437 all callbacks are cleared. */
438 Py_CLEAR(fut->fut_callbacks);
439 return ret;
440 }
441
442 /* we called the first callback, now try calling
443 callbacks from the 'fut_callbacks' list. */
444 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900445
446 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500447 /* No more callbacks, return. */
448 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900449 }
450
451 len = PyList_GET_SIZE(fut->fut_callbacks);
452 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500453 /* The list of callbacks was empty; clear it and return. */
454 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900455 return 0;
456 }
457
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900458 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500459 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
460 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
461 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900462
Yury Selivanov994269c2018-09-27 14:55:55 -0400463 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500464 /* If an error occurs in pure-Python implementation,
465 all callbacks are cleared. */
466 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900467 return -1;
468 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900469 }
470
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500471 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900472 return 0;
473}
474
Oren Milmand019bc82018-02-13 12:28:33 +0200475
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900476static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400477future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900478{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300479 PyObject *res;
480 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900481 _Py_IDENTIFIER(get_debug);
482
Oren Milmand019bc82018-02-13 12:28:33 +0200483 // Same to FutureObj_clear() but not clearing fut->dict
484 Py_CLEAR(fut->fut_loop);
485 Py_CLEAR(fut->fut_callback0);
486 Py_CLEAR(fut->fut_context0);
487 Py_CLEAR(fut->fut_callbacks);
488 Py_CLEAR(fut->fut_result);
489 Py_CLEAR(fut->fut_exception);
490 Py_CLEAR(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700491 Py_CLEAR(fut->fut_cancel_msg);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700492 _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
Oren Milmand019bc82018-02-13 12:28:33 +0200493
494 fut->fut_state = STATE_PENDING;
495 fut->fut_log_tb = 0;
496 fut->fut_blocking = 0;
497
Serhiy Storchakabca49392017-09-03 08:10:14 +0300498 if (loop == Py_None) {
Serhiy Storchaka172c0f22021-04-25 13:40:44 +0300499 loop = get_event_loop(1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900500 if (loop == NULL) {
501 return -1;
502 }
503 }
504 else {
505 Py_INCREF(loop);
506 }
Oren Milmand019bc82018-02-13 12:28:33 +0200507 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900508
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200509 res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900510 if (res == NULL) {
511 return -1;
512 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300513 is_true = PyObject_IsTrue(res);
514 Py_DECREF(res);
515 if (is_true < 0) {
516 return -1;
517 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400518 if (is_true && !_Py_IsFinalizing()) {
519 /* Only try to capture the traceback if the interpreter is not being
520 finalized. The original motivation to add a `_Py_IsFinalizing()`
521 call was to prevent SIGSEGV when a Future is created in a __del__
522 method, which is called during the interpreter shutdown and the
523 traceback module is already unloaded.
524 */
Victor Stinner2ff58a22019-06-17 14:27:23 +0200525 fut->fut_source_tb = PyObject_CallNoArgs(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900526 if (fut->fut_source_tb == NULL) {
527 return -1;
528 }
529 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900530
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900531 return 0;
532}
533
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900534static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400535future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900536{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500537 if (future_ensure_alive(fut)) {
538 return NULL;
539 }
540
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900541 if (fut->fut_state != STATE_PENDING) {
542 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
543 return NULL;
544 }
545
Serhiy Storchakabca49392017-09-03 08:10:14 +0300546 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900547 Py_INCREF(res);
548 fut->fut_result = res;
549 fut->fut_state = STATE_FINISHED;
550
Yury Selivanov22feeb82018-01-24 11:31:01 -0500551 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900552 return NULL;
553 }
554 Py_RETURN_NONE;
555}
556
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900557static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400558future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900559{
560 PyObject *exc_val = NULL;
561
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900562 if (fut->fut_state != STATE_PENDING) {
563 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
564 return NULL;
565 }
566
567 if (PyExceptionClass_Check(exc)) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200568 exc_val = PyObject_CallNoArgs(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900569 if (exc_val == NULL) {
570 return NULL;
571 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300572 if (fut->fut_state != STATE_PENDING) {
573 Py_DECREF(exc_val);
574 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
575 return NULL;
576 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900577 }
578 else {
579 exc_val = exc;
580 Py_INCREF(exc_val);
581 }
582 if (!PyExceptionInstance_Check(exc_val)) {
583 Py_DECREF(exc_val);
584 PyErr_SetString(PyExc_TypeError, "invalid exception object");
585 return NULL;
586 }
Andy Lesterdffe4c02020-03-04 07:15:20 -0600587 if (Py_IS_TYPE(exc_val, (PyTypeObject *)PyExc_StopIteration)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900588 Py_DECREF(exc_val);
589 PyErr_SetString(PyExc_TypeError,
590 "StopIteration interacts badly with generators "
591 "and cannot be raised into a Future");
592 return NULL;
593 }
594
Serhiy Storchakabca49392017-09-03 08:10:14 +0300595 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900596 fut->fut_exception = exc_val;
597 fut->fut_state = STATE_FINISHED;
598
Yury Selivanov22feeb82018-01-24 11:31:01 -0500599 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900600 return NULL;
601 }
602
603 fut->fut_log_tb = 1;
604 Py_RETURN_NONE;
605}
606
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700607static PyObject *
608create_cancelled_error(PyObject *msg)
609{
610 PyObject *exc;
611 if (msg == NULL || msg == Py_None) {
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700612 exc = PyObject_CallNoArgs(asyncio_CancelledError);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700613 } else {
614 exc = PyObject_CallOneArg(asyncio_CancelledError, msg);
615 }
616 return exc;
617}
618
619static void
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700620future_set_cancelled_error(FutureObj *fut)
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700621{
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700622 PyObject *exc = create_cancelled_error(fut->fut_cancel_msg);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700623 PyErr_SetObject(asyncio_CancelledError, exc);
624 Py_DECREF(exc);
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700625
626 _PyErr_ChainStackItem(&fut->fut_cancelled_exc_state);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700627}
628
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400629static int
630future_get_result(FutureObj *fut, PyObject **result)
631{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400632 if (fut->fut_state == STATE_CANCELLED) {
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700633 future_set_cancelled_error(fut);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300634 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400635 }
636
637 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300638 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
639 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400640 }
641
642 fut->fut_log_tb = 0;
643 if (fut->fut_exception != NULL) {
644 Py_INCREF(fut->fut_exception);
645 *result = fut->fut_exception;
646 return 1;
647 }
648
649 Py_INCREF(fut->fut_result);
650 *result = fut->fut_result;
651 return 0;
652}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900653
654static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400655future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900656{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500657 if (!future_is_alive(fut)) {
658 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
659 return NULL;
660 }
661
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900662 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500663 /* The future is done/cancelled, so schedule the callback
664 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500665 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900666 return NULL;
667 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900668 }
669 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500670 /* The future is pending, add a callback.
671
672 Callbacks in the future object are stored as follows:
673
674 callback0 -- a pointer to the first callback
675 callbacks -- a list of 2nd, 3rd, ... callbacks
676
677 Invariants:
678
679 * callbacks != NULL:
680 There are some callbacks in in the list. Just
681 add the new callback to it.
682
683 * callbacks == NULL and callback0 == NULL:
684 This is the first callback. Set it to callback0.
685
686 * callbacks == NULL and callback0 != NULL:
687 This is a second callback. Initialize callbacks
688 with a new list and add the new callback to it.
689 */
690
Yury Selivanovf23746a2018-01-22 19:11:18 -0500691 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500692 Py_INCREF(arg);
693 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500694 Py_INCREF(ctx);
695 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500696 }
697 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500698 PyObject *tup = PyTuple_New(2);
699 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500700 return NULL;
701 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500702 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500703 PyTuple_SET_ITEM(tup, 0, arg);
704 Py_INCREF(ctx);
705 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
706
707 if (fut->fut_callbacks != NULL) {
708 int err = PyList_Append(fut->fut_callbacks, tup);
709 if (err) {
710 Py_DECREF(tup);
711 return NULL;
712 }
713 Py_DECREF(tup);
714 }
715 else {
716 fut->fut_callbacks = PyList_New(1);
717 if (fut->fut_callbacks == NULL) {
Zackery Spytz7b78e7f2020-05-30 02:22:02 -0600718 Py_DECREF(tup);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500719 return NULL;
720 }
721
722 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
723 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900724 }
725 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500726
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900727 Py_RETURN_NONE;
728}
729
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400730static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700731future_cancel(FutureObj *fut, PyObject *msg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400732{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000733 fut->fut_log_tb = 0;
734
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400735 if (fut->fut_state != STATE_PENDING) {
736 Py_RETURN_FALSE;
737 }
738 fut->fut_state = STATE_CANCELLED;
739
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700740 Py_XINCREF(msg);
741 Py_XSETREF(fut->fut_cancel_msg, msg);
742
Yury Selivanov22feeb82018-01-24 11:31:01 -0500743 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400744 return NULL;
745 }
746
747 Py_RETURN_TRUE;
748}
749
750/*[clinic input]
751_asyncio.Future.__init__
752
753 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300754 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400755
756This class is *almost* compatible with concurrent.futures.Future.
757
758 Differences:
759
760 - result() and exception() do not take a timeout argument and
761 raise an exception when the future isn't done yet.
762
763 - Callbacks registered with add_done_callback() are always called
764 via the event loop's call_soon_threadsafe().
765
766 - This class is not compatible with the wait() and as_completed()
767 methods in the concurrent.futures package.
768[clinic start generated code]*/
769
770static int
771_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300772/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400773
774{
775 return future_init(self, loop);
776}
777
778static int
779FutureObj_clear(FutureObj *fut)
780{
781 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500782 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500783 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400784 Py_CLEAR(fut->fut_callbacks);
785 Py_CLEAR(fut->fut_result);
786 Py_CLEAR(fut->fut_exception);
787 Py_CLEAR(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700788 Py_CLEAR(fut->fut_cancel_msg);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700789 _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400790 Py_CLEAR(fut->dict);
791 return 0;
792}
793
794static int
795FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
796{
797 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500798 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500799 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400800 Py_VISIT(fut->fut_callbacks);
801 Py_VISIT(fut->fut_result);
802 Py_VISIT(fut->fut_exception);
803 Py_VISIT(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700804 Py_VISIT(fut->fut_cancel_msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400805 Py_VISIT(fut->dict);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700806
807 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
808 Py_VISIT(exc_state->exc_type);
809 Py_VISIT(exc_state->exc_value);
810 Py_VISIT(exc_state->exc_traceback);
811
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400812 return 0;
813}
814
815/*[clinic input]
816_asyncio.Future.result
817
818Return the result this future represents.
819
820If the future has been cancelled, raises CancelledError. If the
821future's result isn't yet available, raises InvalidStateError. If
822the future is done and has an exception set, this exception is raised.
823[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900824
825static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400826_asyncio_Future_result_impl(FutureObj *self)
827/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
828{
829 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500830
831 if (!future_is_alive(self)) {
832 PyErr_SetString(asyncio_InvalidStateError,
833 "Future object is not initialized.");
834 return NULL;
835 }
836
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400837 int res = future_get_result(self, &result);
838
839 if (res == -1) {
840 return NULL;
841 }
842
843 if (res == 0) {
844 return result;
845 }
846
847 assert(res == 1);
848
849 PyErr_SetObject(PyExceptionInstance_Class(result), result);
850 Py_DECREF(result);
851 return NULL;
852}
853
854/*[clinic input]
855_asyncio.Future.exception
856
857Return the exception that was set on this future.
858
859The exception (or None if no exception was set) is returned only if
860the future is done. If the future has been cancelled, raises
861CancelledError. If the future isn't done yet, raises
862InvalidStateError.
863[clinic start generated code]*/
864
865static PyObject *
866_asyncio_Future_exception_impl(FutureObj *self)
867/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
868{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500869 if (!future_is_alive(self)) {
870 PyErr_SetString(asyncio_InvalidStateError,
871 "Future object is not initialized.");
872 return NULL;
873 }
874
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400875 if (self->fut_state == STATE_CANCELLED) {
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700876 future_set_cancelled_error(self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400877 return NULL;
878 }
879
880 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300881 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400882 return NULL;
883 }
884
885 if (self->fut_exception != NULL) {
886 self->fut_log_tb = 0;
887 Py_INCREF(self->fut_exception);
888 return self->fut_exception;
889 }
890
891 Py_RETURN_NONE;
892}
893
894/*[clinic input]
895_asyncio.Future.set_result
896
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500897 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400898 /
899
900Mark the future done and set its result.
901
902If the future is already done when this method is called, raises
903InvalidStateError.
904[clinic start generated code]*/
905
906static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500907_asyncio_Future_set_result(FutureObj *self, PyObject *result)
908/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400909{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500910 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500911 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400912}
913
914/*[clinic input]
915_asyncio.Future.set_exception
916
Serhiy Storchakabca49392017-09-03 08:10:14 +0300917 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400918 /
919
920Mark the future done and set an exception.
921
922If the future is already done when this method is called, raises
923InvalidStateError.
924[clinic start generated code]*/
925
926static PyObject *
927_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300928/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400929{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500930 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400931 return future_set_exception(self, exception);
932}
933
934/*[clinic input]
935_asyncio.Future.add_done_callback
936
Serhiy Storchakabca49392017-09-03 08:10:14 +0300937 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400938 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500939 *
940 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400941
942Add a callback to be run when the future becomes done.
943
944The callback is called with a single argument - the future object. If
945the future is already done when this is called, the callback is
946scheduled with call_soon.
947[clinic start generated code]*/
948
949static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500950_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
951 PyObject *context)
952/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400953{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500954 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400955 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500956 if (context == NULL) {
957 return NULL;
958 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400959 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500960 Py_DECREF(context);
961 return res;
962 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400963 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400964}
965
966/*[clinic input]
967_asyncio.Future.remove_done_callback
968
Serhiy Storchakabca49392017-09-03 08:10:14 +0300969 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400970 /
971
972Remove all instances of a callback from the "call when done" list.
973
974Returns the number of callbacks removed.
975[clinic start generated code]*/
976
977static PyObject *
978_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300979/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900980{
981 PyObject *newlist;
982 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500983 Py_ssize_t cleared_callback0 = 0;
984
985 ENSURE_FUTURE_ALIVE(self)
986
987 if (self->fut_callback0 != NULL) {
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300988 int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500989 if (cmp == -1) {
990 return NULL;
991 }
992 if (cmp == 1) {
993 /* callback0 == fn */
994 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500995 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500996 cleared_callback0 = 1;
997 }
998 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900999
Serhiy Storchakabca49392017-09-03 08:10:14 +03001000 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001001 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001002 }
1003
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001004 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001005 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001006 Py_CLEAR(self->fut_callbacks);
1007 return PyLong_FromSsize_t(cleared_callback0);
1008 }
1009
1010 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -05001011 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001012 int cmp = PyObject_RichCompareBool(
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001013 PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001014 if (cmp == -1) {
1015 return NULL;
1016 }
1017 if (cmp == 1) {
1018 /* callbacks[0] == fn */
1019 Py_CLEAR(self->fut_callbacks);
1020 return PyLong_FromSsize_t(1 + cleared_callback0);
1021 }
1022 /* callbacks[0] != fn and len(callbacks) == 1 */
1023 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001024 }
1025
1026 newlist = PyList_New(len);
1027 if (newlist == NULL) {
1028 return NULL;
1029 }
1030
Yury Selivanov84af9032017-03-02 23:46:56 -05001031 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001032 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001033 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001034 Py_INCREF(item);
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001035 ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001036 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001037 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001038 PyList_SET_ITEM(newlist, j, item);
1039 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001040 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -04001041 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001042 ret = PyList_Append(newlist, item);
1043 }
1044 Py_DECREF(item);
1045 if (ret < 0) {
1046 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001047 }
1048 }
1049
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001050 if (j == 0) {
1051 Py_CLEAR(self->fut_callbacks);
1052 Py_DECREF(newlist);
1053 return PyLong_FromSsize_t(len + cleared_callback0);
1054 }
1055
Serhiy Storchakabca49392017-09-03 08:10:14 +03001056 if (j < len) {
Victor Stinner60ac6ed2020-02-07 23:18:08 +01001057 Py_SET_SIZE(newlist, j);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001058 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001059 j = PyList_GET_SIZE(newlist);
1060 len = PyList_GET_SIZE(self->fut_callbacks);
1061 if (j != len) {
1062 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1063 goto fail;
1064 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001065 }
1066 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001067 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001068
1069fail:
1070 Py_DECREF(newlist);
1071 return NULL;
1072}
1073
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001074/*[clinic input]
1075_asyncio.Future.cancel
1076
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001077 msg: object = None
1078
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001079Cancel the future and schedule callbacks.
1080
1081If the future is already done or cancelled, return False. Otherwise,
1082change the future's state to cancelled, schedule the callbacks and
1083return True.
1084[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001085
1086static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001087_asyncio_Future_cancel_impl(FutureObj *self, PyObject *msg)
1088/*[clinic end generated code: output=3edebbc668e5aba3 input=925eb545251f2c5a]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001089{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001090 ENSURE_FUTURE_ALIVE(self)
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001091 return future_cancel(self, msg);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001092}
1093
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001094/*[clinic input]
1095_asyncio.Future.cancelled
1096
1097Return True if the future was cancelled.
1098[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001099
1100static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001101_asyncio_Future_cancelled_impl(FutureObj *self)
1102/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001103{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001104 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001105 Py_RETURN_TRUE;
1106 }
1107 else {
1108 Py_RETURN_FALSE;
1109 }
1110}
1111
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001112/*[clinic input]
1113_asyncio.Future.done
1114
1115Return True if the future is done.
1116
1117Done means either that a result / exception are available, or that the
1118future was cancelled.
1119[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001120
1121static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001122_asyncio_Future_done_impl(FutureObj *self)
1123/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001124{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001125 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001126 Py_RETURN_FALSE;
1127 }
1128 else {
1129 Py_RETURN_TRUE;
1130 }
1131}
1132
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001133/*[clinic input]
1134_asyncio.Future.get_loop
1135
1136Return the event loop the Future is bound to.
1137[clinic start generated code]*/
1138
1139static PyObject *
1140_asyncio_Future_get_loop_impl(FutureObj *self)
1141/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1142{
Andrew Svetlovdad6be52019-11-13 23:36:46 +02001143 ENSURE_FUTURE_ALIVE(self)
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001144 Py_INCREF(self->fut_loop);
1145 return self->fut_loop;
1146}
1147
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001148static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001149FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001150{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001151 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001152 Py_RETURN_TRUE;
1153 }
1154 else {
1155 Py_RETURN_FALSE;
1156 }
1157}
1158
1159static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001160FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001161{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001162 if (future_ensure_alive(fut)) {
1163 return -1;
1164 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001165 if (val == NULL) {
1166 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1167 return -1;
1168 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001169
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001170 int is_true = PyObject_IsTrue(val);
1171 if (is_true < 0) {
1172 return -1;
1173 }
1174 fut->fut_blocking = is_true;
1175 return 0;
1176}
1177
1178static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001179FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001180{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001181 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001182 if (fut->fut_log_tb) {
1183 Py_RETURN_TRUE;
1184 }
1185 else {
1186 Py_RETURN_FALSE;
1187 }
1188}
1189
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001190static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001191FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001192{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001193 if (val == NULL) {
1194 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1195 return -1;
1196 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001197 int is_true = PyObject_IsTrue(val);
1198 if (is_true < 0) {
1199 return -1;
1200 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001201 if (is_true) {
1202 PyErr_SetString(PyExc_ValueError,
1203 "_log_traceback can only be set to False");
1204 return -1;
1205 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001206 fut->fut_log_tb = is_true;
1207 return 0;
1208}
1209
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001210static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001211FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001212{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001213 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001214 Py_RETURN_NONE;
1215 }
1216 Py_INCREF(fut->fut_loop);
1217 return fut->fut_loop;
1218}
1219
1220static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001221FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001222{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001223 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001224
1225 ENSURE_FUTURE_ALIVE(fut)
1226
Yury Selivanovf23746a2018-01-22 19:11:18 -05001227 if (fut->fut_callback0 == NULL) {
1228 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001229 Py_RETURN_NONE;
1230 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001231
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001232 Py_INCREF(fut->fut_callbacks);
1233 return fut->fut_callbacks;
1234 }
1235
Yury Selivanovf23746a2018-01-22 19:11:18 -05001236 Py_ssize_t len = 1;
1237 if (fut->fut_callbacks != NULL) {
1238 len += PyList_GET_SIZE(fut->fut_callbacks);
1239 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001240
Yury Selivanovf23746a2018-01-22 19:11:18 -05001241
1242 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001243 if (new_list == NULL) {
1244 return NULL;
1245 }
1246
Yury Selivanovf23746a2018-01-22 19:11:18 -05001247 PyObject *tup0 = PyTuple_New(2);
1248 if (tup0 == NULL) {
1249 Py_DECREF(new_list);
1250 return NULL;
1251 }
1252
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001253 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001254 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1255 assert(fut->fut_context0 != NULL);
1256 Py_INCREF(fut->fut_context0);
1257 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1258
1259 PyList_SET_ITEM(new_list, 0, tup0);
1260
1261 if (fut->fut_callbacks != NULL) {
1262 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1263 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1264 Py_INCREF(cb);
1265 PyList_SET_ITEM(new_list, i + 1, cb);
1266 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001267 }
1268
1269 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001270}
1271
1272static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001273FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001274{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001275 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001276 if (fut->fut_result == NULL) {
1277 Py_RETURN_NONE;
1278 }
1279 Py_INCREF(fut->fut_result);
1280 return fut->fut_result;
1281}
1282
1283static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001284FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001285{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001286 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001287 if (fut->fut_exception == NULL) {
1288 Py_RETURN_NONE;
1289 }
1290 Py_INCREF(fut->fut_exception);
1291 return fut->fut_exception;
1292}
1293
1294static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001295FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001296{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001297 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001298 Py_RETURN_NONE;
1299 }
1300 Py_INCREF(fut->fut_source_tb);
1301 return fut->fut_source_tb;
1302}
1303
1304static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001305FutureObj_get_cancel_message(FutureObj *fut, void *Py_UNUSED(ignored))
1306{
1307 if (fut->fut_cancel_msg == NULL) {
1308 Py_RETURN_NONE;
1309 }
1310 Py_INCREF(fut->fut_cancel_msg);
1311 return fut->fut_cancel_msg;
1312}
1313
1314static int
1315FutureObj_set_cancel_message(FutureObj *fut, PyObject *msg,
1316 void *Py_UNUSED(ignored))
1317{
1318 if (msg == NULL) {
1319 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1320 return -1;
1321 }
1322 Py_INCREF(msg);
1323 Py_XSETREF(fut->fut_cancel_msg, msg);
1324 return 0;
1325}
1326
1327static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001328FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001329{
1330 _Py_IDENTIFIER(PENDING);
1331 _Py_IDENTIFIER(CANCELLED);
1332 _Py_IDENTIFIER(FINISHED);
1333 PyObject *ret = NULL;
1334
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001335 ENSURE_FUTURE_ALIVE(fut)
1336
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001337 switch (fut->fut_state) {
1338 case STATE_PENDING:
1339 ret = _PyUnicode_FromId(&PyId_PENDING);
1340 break;
1341 case STATE_CANCELLED:
1342 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1343 break;
1344 case STATE_FINISHED:
1345 ret = _PyUnicode_FromId(&PyId_FINISHED);
1346 break;
1347 default:
1348 assert (0);
1349 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001350 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001351 return ret;
1352}
1353
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001354/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001355_asyncio.Future._make_cancelled_error
1356
1357Create the CancelledError to raise if the Future is cancelled.
1358
1359This should only be called once when handling a cancellation since
1360it erases the context exception value.
1361[clinic start generated code]*/
1362
1363static PyObject *
1364_asyncio_Future__make_cancelled_error_impl(FutureObj *self)
1365/*[clinic end generated code: output=a5df276f6c1213de input=ac6effe4ba795ecc]*/
1366{
1367 PyObject *exc = create_cancelled_error(self->fut_cancel_msg);
1368 _PyErr_StackItem *exc_state = &self->fut_cancelled_exc_state;
1369 /* Transfer ownership of exc_value from exc_state to exc since we are
1370 done with it. */
1371 PyException_SetContext(exc, exc_state->exc_value);
1372 exc_state->exc_value = NULL;
1373
1374 return exc;
1375}
1376
1377/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001378_asyncio.Future._repr_info
1379[clinic start generated code]*/
1380
1381static PyObject *
1382_asyncio_Future__repr_info_impl(FutureObj *self)
1383/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001384{
Petr Viktorinffd97532020-02-11 17:46:57 +01001385 return PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001386}
1387
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001388static PyObject *
1389FutureObj_repr(FutureObj *fut)
1390{
1391 _Py_IDENTIFIER(_repr_info);
1392
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001393 ENSURE_FUTURE_ALIVE(fut)
1394
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001395 PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
1396 &PyId__repr_info);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001397 if (rinfo == NULL) {
1398 return NULL;
1399 }
1400
Serhiy Storchakabca49392017-09-03 08:10:14 +03001401 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001402 Py_DECREF(rinfo);
1403 if (rinfo_s == NULL) {
1404 return NULL;
1405 }
1406
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001407 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1408 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001409 Py_DECREF(rinfo_s);
1410 return rstr;
1411}
1412
1413static void
1414FutureObj_finalize(FutureObj *fut)
1415{
1416 _Py_IDENTIFIER(call_exception_handler);
1417 _Py_IDENTIFIER(message);
1418 _Py_IDENTIFIER(exception);
1419 _Py_IDENTIFIER(future);
1420 _Py_IDENTIFIER(source_traceback);
1421
Serhiy Storchakabca49392017-09-03 08:10:14 +03001422 PyObject *error_type, *error_value, *error_traceback;
1423 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001424 PyObject *message = NULL;
1425 PyObject *func;
1426
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001427 if (!fut->fut_log_tb) {
1428 return;
1429 }
1430 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001431 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001432
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001433 /* Save the current exception, if any. */
1434 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1435
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001436 context = PyDict_New();
1437 if (context == NULL) {
1438 goto finally;
1439 }
1440
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001441 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001442 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001443 if (message == NULL) {
1444 goto finally;
1445 }
1446
1447 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1448 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1449 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1450 goto finally;
1451 }
1452 if (fut->fut_source_tb != NULL) {
1453 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1454 fut->fut_source_tb) < 0) {
1455 goto finally;
1456 }
1457 }
1458
1459 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1460 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01001461 PyObject *res = PyObject_CallOneArg(func, context);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001462 if (res == NULL) {
1463 PyErr_WriteUnraisable(func);
1464 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001465 else {
1466 Py_DECREF(res);
1467 }
1468 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001469 }
1470
1471finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001472 Py_XDECREF(context);
1473 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001474
1475 /* Restore the saved exception. */
1476 PyErr_Restore(error_type, error_value, error_traceback);
1477}
1478
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001479static PyObject *
1480future_cls_getitem(PyObject *cls, PyObject *type)
1481{
1482 Py_INCREF(cls);
1483 return cls;
1484}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001485
1486static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001487 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001488 0, /* am_aiter */
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001489 0, /* am_anext */
1490 0, /* am_send */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001491};
1492
1493static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001494 _ASYNCIO_FUTURE_RESULT_METHODDEF
1495 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1496 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1497 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1498 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1499 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1500 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1501 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1502 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001503 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001504 _ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001505 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001506 {"__class_getitem__", future_cls_getitem, METH_O|METH_CLASS, NULL},
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001507 {NULL, NULL} /* Sentinel */
1508};
1509
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001510#define FUTURE_COMMON_GETSETLIST \
1511 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1512 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1513 (setter)FutureObj_set_blocking, NULL}, \
1514 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1515 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1516 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1517 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001518 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1519 (setter)FutureObj_set_log_traceback, NULL}, \
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001520 {"_source_traceback", (getter)FutureObj_get_source_traceback, \
1521 NULL, NULL}, \
1522 {"_cancel_message", (getter)FutureObj_get_cancel_message, \
1523 (setter)FutureObj_set_cancel_message, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001524
1525static PyGetSetDef FutureType_getsetlist[] = {
1526 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001527 {NULL} /* Sentinel */
1528};
1529
1530static void FutureObj_dealloc(PyObject *self);
1531
1532static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001533 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001534 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001535 sizeof(FutureObj), /* tp_basicsize */
1536 .tp_dealloc = FutureObj_dealloc,
1537 .tp_as_async = &FutureType_as_async,
1538 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001539 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001540 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001541 .tp_traverse = (traverseproc)FutureObj_traverse,
1542 .tp_clear = (inquiry)FutureObj_clear,
1543 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001544 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001545 .tp_methods = FutureType_methods,
1546 .tp_getset = FutureType_getsetlist,
1547 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001548 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001549 .tp_new = PyType_GenericNew,
1550 .tp_finalize = (destructor)FutureObj_finalize,
1551};
1552
1553static void
1554FutureObj_dealloc(PyObject *self)
1555{
1556 FutureObj *fut = (FutureObj *)self;
1557
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001558 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001559 /* When fut is subclass of Future, finalizer is called from
1560 * subtype_dealloc.
1561 */
1562 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1563 // resurrected.
1564 return;
1565 }
1566 }
1567
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001568 PyObject_GC_UnTrack(self);
1569
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001570 if (fut->fut_weakreflist != NULL) {
1571 PyObject_ClearWeakRefs(self);
1572 }
1573
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001574 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001575 Py_TYPE(fut)->tp_free(fut);
1576}
1577
1578
1579/*********************** Future Iterator **************************/
1580
1581typedef struct {
1582 PyObject_HEAD
1583 FutureObj *future;
1584} futureiterobject;
1585
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001586
1587#define FI_FREELIST_MAXLEN 255
1588static futureiterobject *fi_freelist = NULL;
1589static Py_ssize_t fi_freelist_len = 0;
1590
1591
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001592static void
1593FutureIter_dealloc(futureiterobject *it)
1594{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001595 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001596 Py_CLEAR(it->future);
1597
1598 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1599 fi_freelist_len++;
1600 it->future = (FutureObj*) fi_freelist;
1601 fi_freelist = it;
1602 }
1603 else {
1604 PyObject_GC_Del(it);
1605 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001606}
1607
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001608static PySendResult
1609FutureIter_am_send(futureiterobject *it,
1610 PyObject *Py_UNUSED(arg),
1611 PyObject **result)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001612{
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001613 /* arg is unused, see the comment on FutureIter_send for clarification */
1614
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001615 PyObject *res;
1616 FutureObj *fut = it->future;
1617
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001618 *result = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001619 if (fut == NULL) {
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001620 return PYGEN_ERROR;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001621 }
1622
1623 if (fut->fut_state == STATE_PENDING) {
1624 if (!fut->fut_blocking) {
1625 fut->fut_blocking = 1;
1626 Py_INCREF(fut);
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001627 *result = (PyObject *)fut;
1628 return PYGEN_NEXT;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001629 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001630 PyErr_SetString(PyExc_RuntimeError,
1631 "await wasn't used with future");
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001632 return PYGEN_ERROR;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001633 }
1634
Serhiy Storchakabca49392017-09-03 08:10:14 +03001635 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001636 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001637 if (res != NULL) {
Andrew Svetlovcda99b42020-11-11 17:48:53 +02001638 Py_DECREF(fut);
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001639 *result = res;
1640 return PYGEN_RETURN;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001641 }
1642
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001643 Py_DECREF(fut);
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001644 return PYGEN_ERROR;
1645}
1646
1647static PyObject *
1648FutureIter_iternext(futureiterobject *it)
1649{
1650 PyObject *result;
1651 switch (FutureIter_am_send(it, Py_None, &result)) {
1652 case PYGEN_RETURN:
1653 (void)_PyGen_SetStopIterationValue(result);
1654 Py_DECREF(result);
1655 return NULL;
1656 case PYGEN_NEXT:
1657 return result;
1658 case PYGEN_ERROR:
1659 return NULL;
1660 default:
1661 Py_UNREACHABLE();
1662 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001663}
1664
1665static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001666FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001667{
INADA Naoki74c17532016-10-25 19:00:45 +09001668 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001669 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001670 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001671 return FutureIter_iternext(self);
1672}
1673
1674static PyObject *
1675FutureIter_throw(futureiterobject *self, PyObject *args)
1676{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001677 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001678 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1679 return NULL;
1680
1681 if (val == Py_None) {
1682 val = NULL;
1683 }
1684 if (tb == Py_None) {
1685 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001686 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1687 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1688 return NULL;
1689 }
1690
1691 Py_INCREF(type);
1692 Py_XINCREF(val);
1693 Py_XINCREF(tb);
1694
1695 if (PyExceptionClass_Check(type)) {
1696 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001697 /* No need to call PyException_SetTraceback since we'll be calling
1698 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001699 } else if (PyExceptionInstance_Check(type)) {
1700 if (val) {
1701 PyErr_SetString(PyExc_TypeError,
1702 "instance exception may not have a separate value");
1703 goto fail;
1704 }
1705 val = type;
1706 type = PyExceptionInstance_Class(type);
1707 Py_INCREF(type);
1708 if (tb == NULL)
1709 tb = PyException_GetTraceback(val);
1710 } else {
1711 PyErr_SetString(PyExc_TypeError,
1712 "exceptions must be classes deriving BaseException or "
1713 "instances of such a class");
1714 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001715 }
1716
1717 Py_CLEAR(self->future);
1718
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001719 PyErr_Restore(type, val, tb);
1720
Serhiy Storchakabca49392017-09-03 08:10:14 +03001721 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001722
1723 fail:
1724 Py_DECREF(type);
1725 Py_XDECREF(val);
1726 Py_XDECREF(tb);
1727 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001728}
1729
1730static PyObject *
1731FutureIter_close(futureiterobject *self, PyObject *arg)
1732{
1733 Py_CLEAR(self->future);
1734 Py_RETURN_NONE;
1735}
1736
1737static int
1738FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1739{
1740 Py_VISIT(it->future);
1741 return 0;
1742}
1743
1744static PyMethodDef FutureIter_methods[] = {
1745 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1746 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1747 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1748 {NULL, NULL} /* Sentinel */
1749};
1750
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001751static PyAsyncMethods FutureIterType_as_async = {
1752 0, /* am_await */
1753 0, /* am_aiter */
1754 0, /* am_anext */
1755 (sendfunc)FutureIter_am_send, /* am_send */
1756};
1757
1758
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001759static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001760 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001761 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001762 .tp_basicsize = sizeof(futureiterobject),
1763 .tp_itemsize = 0,
1764 .tp_dealloc = (destructor)FutureIter_dealloc,
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001765 .tp_as_async = &FutureIterType_as_async,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001766 .tp_getattro = PyObject_GenericGetAttr,
Miss Islington (bot)632e8a62021-07-23 07:56:53 -07001767 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001768 .tp_traverse = (traverseproc)FutureIter_traverse,
1769 .tp_iter = PyObject_SelfIter,
1770 .tp_iternext = (iternextfunc)FutureIter_iternext,
1771 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001772};
1773
1774static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001775future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001776{
1777 futureiterobject *it;
1778
1779 if (!PyObject_TypeCheck(fut, &FutureType)) {
1780 PyErr_BadInternalCall();
1781 return NULL;
1782 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001783
1784 ENSURE_FUTURE_ALIVE(fut)
1785
1786 if (fi_freelist_len) {
1787 fi_freelist_len--;
1788 it = fi_freelist;
1789 fi_freelist = (futureiterobject*) it->future;
1790 it->future = NULL;
1791 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001792 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001793 else {
1794 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1795 if (it == NULL) {
1796 return NULL;
1797 }
1798 }
1799
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001800 Py_INCREF(fut);
1801 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001802 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001803 return (PyObject*)it;
1804}
1805
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001806
1807/*********************** Task **************************/
1808
1809
1810/*[clinic input]
1811class _asyncio.Task "TaskObj *" "&Task_Type"
1812[clinic start generated code]*/
1813/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1814
1815static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001816static PyObject * task_wakeup(TaskObj *, PyObject *);
1817static PyObject * task_step(TaskObj *, PyObject *);
1818
1819/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001820
INADA Naokic411a7d2016-10-18 11:48:14 +09001821static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001822TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001823{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001824 Py_CLEAR(o->sw_task);
1825 Py_CLEAR(o->sw_arg);
1826 return 0;
1827}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001828
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001829static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001830TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001831{
1832 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001833 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001834 Py_TYPE(o)->tp_free(o);
1835}
1836
1837static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001838TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001839 PyObject *args, PyObject *kwds)
1840{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001841 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1842 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1843 return NULL;
1844 }
1845 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1846 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1847 return NULL;
1848 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001849 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001850}
1851
1852static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001853TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001854 visitproc visit, void *arg)
1855{
1856 Py_VISIT(o->sw_task);
1857 Py_VISIT(o->sw_arg);
1858 return 0;
1859}
1860
1861static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001862TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001863{
1864 if (o->sw_task) {
1865 Py_INCREF(o->sw_task);
1866 return (PyObject*)o->sw_task;
1867 }
1868 Py_RETURN_NONE;
1869}
1870
Serhiy Storchakabca49392017-09-03 08:10:14 +03001871static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1872 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001873 {NULL} /* Sentinel */
1874};
1875
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001876static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001877 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001878 "TaskStepMethWrapper",
1879 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001880 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001881 .tp_getset = TaskStepMethWrapper_getsetlist,
1882 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1883 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001884 .tp_getattro = PyObject_GenericGetAttr,
1885 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001886 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1887 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001888};
1889
1890static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001891TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001892{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001893 TaskStepMethWrapper *o;
1894 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001895 if (o == NULL) {
1896 return NULL;
1897 }
1898
1899 Py_INCREF(task);
1900 o->sw_task = task;
1901
1902 Py_XINCREF(arg);
1903 o->sw_arg = arg;
1904
1905 PyObject_GC_Track(o);
1906 return (PyObject*) o;
1907}
1908
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07001909/* ----- Task._wakeup implementation */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001910
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07001911static PyMethodDef TaskWakeupDef = {
1912 "task_wakeup",
1913 (PyCFunction)task_wakeup,
1914 METH_O,
1915 NULL
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001916};
1917
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001918/* ----- Task introspection helpers */
1919
1920static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001921register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001922{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001923 _Py_IDENTIFIER(add);
1924
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001925 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1926 &PyId_add, task);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001927 if (res == NULL) {
1928 return -1;
1929 }
1930 Py_DECREF(res);
1931 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001932}
1933
1934
1935static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001936unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001937{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001938 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001939
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001940 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1941 &PyId_discard, task);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001942 if (res == NULL) {
1943 return -1;
1944 }
1945 Py_DECREF(res);
1946 return 0;
1947}
1948
1949
1950static int
1951enter_task(PyObject *loop, PyObject *task)
1952{
1953 PyObject *item;
1954 Py_hash_t hash;
1955 hash = PyObject_Hash(loop);
1956 if (hash == -1) {
1957 return -1;
1958 }
1959 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1960 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001961 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001962 PyErr_Format(
1963 PyExc_RuntimeError,
1964 "Cannot enter into task %R while another " \
1965 "task %R is being executed.",
1966 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001967 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001968 return -1;
1969 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001970 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001971 return -1;
1972 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001973 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001974}
1975
1976
1977static int
1978leave_task(PyObject *loop, PyObject *task)
1979/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1980{
1981 PyObject *item;
1982 Py_hash_t hash;
1983 hash = PyObject_Hash(loop);
1984 if (hash == -1) {
1985 return -1;
1986 }
1987 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1988 if (item != task) {
1989 if (item == NULL) {
1990 /* Not entered, replace with None */
1991 item = Py_None;
1992 }
1993 PyErr_Format(
1994 PyExc_RuntimeError,
1995 "Leaving task %R does not match the current task %R.",
1996 task, item, NULL);
1997 return -1;
1998 }
1999 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
2000}
2001
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002002/* ----- Task */
2003
2004/*[clinic input]
2005_asyncio.Task.__init__
2006
Serhiy Storchakabca49392017-09-03 08:10:14 +03002007 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002008 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002009 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002010 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002011
2012A coroutine wrapped in a Future.
2013[clinic start generated code]*/
2014
2015static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002016_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2017 PyObject *name)
2018/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002019{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002020 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002021 return -1;
2022 }
INADA Naokic411a7d2016-10-18 11:48:14 +09002023
Yury Selivanova9d7e552017-12-19 07:18:45 -05002024 int is_coro = is_coroutine(coro);
2025 if (is_coro == -1) {
2026 return -1;
2027 }
2028 if (is_coro == 0) {
2029 self->task_log_destroy_pending = 0;
2030 PyErr_Format(PyExc_TypeError,
2031 "a coroutine was expected, got %R",
2032 coro, NULL);
2033 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02002034 }
2035
Oren Milmand019bc82018-02-13 12:28:33 +02002036 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05002037 if (self->task_context == NULL) {
2038 return -1;
2039 }
2040
Oren Milmand019bc82018-02-13 12:28:33 +02002041 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002042 self->task_must_cancel = 0;
2043 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002044 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02002045 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002046
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002047 if (name == Py_None) {
2048 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03002049 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002050 name = PyObject_Str(name);
2051 } else {
2052 Py_INCREF(name);
2053 }
2054 Py_XSETREF(self->task_name, name);
2055 if (self->task_name == NULL) {
2056 return -1;
2057 }
2058
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002059 if (task_call_step_soon(self, NULL)) {
2060 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09002061 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002062 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002063}
2064
2065static int
2066TaskObj_clear(TaskObj *task)
2067{
2068 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002069 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002070 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002071 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002072 Py_CLEAR(task->task_fut_waiter);
2073 return 0;
2074}
2075
2076static int
2077TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2078{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002079 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002080 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002081 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002082 Py_VISIT(task->task_fut_waiter);
2083 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2084 return 0;
2085}
2086
2087static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002088TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002089{
2090 if (task->task_log_destroy_pending) {
2091 Py_RETURN_TRUE;
2092 }
2093 else {
2094 Py_RETURN_FALSE;
2095 }
2096}
2097
2098static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002099TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002100{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002101 if (val == NULL) {
2102 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2103 return -1;
2104 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002105 int is_true = PyObject_IsTrue(val);
2106 if (is_true < 0) {
2107 return -1;
2108 }
2109 task->task_log_destroy_pending = is_true;
2110 return 0;
2111}
2112
2113static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002114TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002115{
2116 if (task->task_must_cancel) {
2117 Py_RETURN_TRUE;
2118 }
2119 else {
2120 Py_RETURN_FALSE;
2121 }
2122}
2123
2124static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002125TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002126{
2127 if (task->task_coro) {
2128 Py_INCREF(task->task_coro);
2129 return task->task_coro;
2130 }
2131
2132 Py_RETURN_NONE;
2133}
2134
2135static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002136TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002137{
2138 if (task->task_fut_waiter) {
2139 Py_INCREF(task->task_fut_waiter);
2140 return task->task_fut_waiter;
2141 }
2142
2143 Py_RETURN_NONE;
2144}
2145
2146/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002147_asyncio.Task._make_cancelled_error
2148
2149Create the CancelledError to raise if the Task is cancelled.
2150
2151This should only be called once when handling a cancellation since
2152it erases the context exception value.
2153[clinic start generated code]*/
2154
2155static PyObject *
2156_asyncio_Task__make_cancelled_error_impl(TaskObj *self)
2157/*[clinic end generated code: output=55a819e8b4276fab input=52c0e32de8e2f840]*/
2158{
2159 FutureObj *fut = (FutureObj*)self;
2160 return _asyncio_Future__make_cancelled_error_impl(fut);
2161}
2162
2163
2164/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002165_asyncio.Task._repr_info
2166[clinic start generated code]*/
2167
2168static PyObject *
2169_asyncio_Task__repr_info_impl(TaskObj *self)
2170/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2171{
Petr Viktorinffd97532020-02-11 17:46:57 +01002172 return PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002173}
2174
2175/*[clinic input]
2176_asyncio.Task.cancel
2177
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002178 msg: object = None
2179
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002180Request that this task cancel itself.
2181
2182This arranges for a CancelledError to be thrown into the
2183wrapped coroutine on the next cycle through the event loop.
2184The coroutine then has a chance to clean up or even deny
2185the request using try/except/finally.
2186
2187Unlike Future.cancel, this does not guarantee that the
2188task will be cancelled: the exception might be caught and
2189acted upon, delaying cancellation of the task or preventing
2190cancellation completely. The task may also return a value or
2191raise a different exception.
2192
2193Immediately after this method is called, Task.cancelled() will
2194not return True (unless the task was already cancelled). A
2195task will be marked as cancelled when the wrapped coroutine
2196terminates with a CancelledError exception (even if cancel()
2197was not called).
2198[clinic start generated code]*/
2199
2200static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002201_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
2202/*[clinic end generated code: output=c66b60d41c74f9f1 input=f4ff8e8ffc5f1c00]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002203{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002204 self->task_log_tb = 0;
2205
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002206 if (self->task_state != STATE_PENDING) {
2207 Py_RETURN_FALSE;
2208 }
2209
2210 if (self->task_fut_waiter) {
2211 PyObject *res;
2212 int is_true;
2213
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002214 res = _PyObject_CallMethodIdOneArg(self->task_fut_waiter,
2215 &PyId_cancel, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002216 if (res == NULL) {
2217 return NULL;
2218 }
2219
2220 is_true = PyObject_IsTrue(res);
2221 Py_DECREF(res);
2222 if (is_true < 0) {
2223 return NULL;
2224 }
2225
2226 if (is_true) {
2227 Py_RETURN_TRUE;
2228 }
2229 }
2230
2231 self->task_must_cancel = 1;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002232 Py_XINCREF(msg);
2233 Py_XSETREF(self->task_cancel_msg, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002234 Py_RETURN_TRUE;
2235}
2236
2237/*[clinic input]
2238_asyncio.Task.get_stack
2239
2240 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002241 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002242
2243Return the list of stack frames for this task's coroutine.
2244
2245If the coroutine is not done, this returns the stack where it is
2246suspended. If the coroutine has completed successfully or was
2247cancelled, this returns an empty list. If the coroutine was
2248terminated by an exception, this returns the list of traceback
2249frames.
2250
2251The frames are always ordered from oldest to newest.
2252
2253The optional limit gives the maximum number of frames to
2254return; by default all available frames are returned. Its
2255meaning differs depending on whether a stack or a traceback is
2256returned: the newest frames of a stack are returned, but the
2257oldest frames of a traceback are returned. (This matches the
2258behavior of the traceback module.)
2259
2260For reasons beyond our control, only one stack frame is
2261returned for a suspended coroutine.
2262[clinic start generated code]*/
2263
2264static PyObject *
2265_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002266/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002267{
2268 return PyObject_CallFunctionObjArgs(
2269 asyncio_task_get_stack_func, self, limit, NULL);
2270}
2271
2272/*[clinic input]
2273_asyncio.Task.print_stack
2274
2275 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002276 limit: object = None
2277 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002278
2279Print the stack or traceback for this task's coroutine.
2280
2281This produces output similar to that of the traceback module,
2282for the frames retrieved by get_stack(). The limit argument
2283is passed to get_stack(). The file argument is an I/O stream
2284to which the output is written; by default output is written
2285to sys.stderr.
2286[clinic start generated code]*/
2287
2288static PyObject *
2289_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2290 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002291/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002292{
2293 return PyObject_CallFunctionObjArgs(
2294 asyncio_task_print_stack_func, self, limit, file, NULL);
2295}
2296
2297/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002298_asyncio.Task.set_result
2299
2300 result: object
2301 /
2302[clinic start generated code]*/
2303
2304static PyObject *
2305_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2306/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2307{
2308 PyErr_SetString(PyExc_RuntimeError,
2309 "Task does not support set_result operation");
2310 return NULL;
2311}
2312
2313/*[clinic input]
2314_asyncio.Task.set_exception
2315
2316 exception: object
2317 /
2318[clinic start generated code]*/
2319
2320static PyObject *
2321_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2322/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2323{
2324 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002325 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002326 return NULL;
2327}
2328
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002329/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002330_asyncio.Task.get_coro
2331[clinic start generated code]*/
2332
2333static PyObject *
2334_asyncio_Task_get_coro_impl(TaskObj *self)
2335/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2336{
2337 Py_INCREF(self->task_coro);
2338 return self->task_coro;
2339}
2340
2341/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002342_asyncio.Task.get_name
2343[clinic start generated code]*/
2344
2345static PyObject *
2346_asyncio_Task_get_name_impl(TaskObj *self)
2347/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2348{
2349 if (self->task_name) {
2350 Py_INCREF(self->task_name);
2351 return self->task_name;
2352 }
2353
2354 Py_RETURN_NONE;
2355}
2356
2357/*[clinic input]
2358_asyncio.Task.set_name
2359
2360 value: object
2361 /
2362[clinic start generated code]*/
2363
2364static PyObject *
2365_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2366/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2367{
Alex Grönholma7548232018-08-09 23:49:49 +03002368 if (!PyUnicode_CheckExact(value)) {
2369 value = PyObject_Str(value);
2370 if (value == NULL) {
2371 return NULL;
2372 }
2373 } else {
2374 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002375 }
2376
Alex Grönholma7548232018-08-09 23:49:49 +03002377 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002378 Py_RETURN_NONE;
2379}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002380
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002381static void
2382TaskObj_finalize(TaskObj *task)
2383{
2384 _Py_IDENTIFIER(call_exception_handler);
2385 _Py_IDENTIFIER(task);
2386 _Py_IDENTIFIER(message);
2387 _Py_IDENTIFIER(source_traceback);
2388
Serhiy Storchakabca49392017-09-03 08:10:14 +03002389 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002390 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002391 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002392 PyObject *error_type, *error_value, *error_traceback;
2393
2394 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2395 goto done;
2396 }
2397
2398 /* Save the current exception, if any. */
2399 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2400
2401 context = PyDict_New();
2402 if (context == NULL) {
2403 goto finally;
2404 }
2405
2406 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2407 if (message == NULL) {
2408 goto finally;
2409 }
2410
2411 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2412 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2413 {
2414 goto finally;
2415 }
2416
2417 if (task->task_source_tb != NULL) {
2418 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2419 task->task_source_tb) < 0)
2420 {
2421 goto finally;
2422 }
2423 }
2424
2425 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2426 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01002427 PyObject *res = PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002428 if (res == NULL) {
2429 PyErr_WriteUnraisable(func);
2430 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002431 else {
2432 Py_DECREF(res);
2433 }
2434 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002435 }
2436
2437finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002438 Py_XDECREF(context);
2439 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002440
2441 /* Restore the saved exception. */
2442 PyErr_Restore(error_type, error_value, error_traceback);
2443
2444done:
2445 FutureObj_finalize((FutureObj*)task);
2446}
2447
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002448static PyObject *
2449task_cls_getitem(PyObject *cls, PyObject *type)
2450{
2451 Py_INCREF(cls);
2452 return cls;
2453}
2454
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002455static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2456
2457static PyMethodDef TaskType_methods[] = {
2458 _ASYNCIO_FUTURE_RESULT_METHODDEF
2459 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002460 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2461 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2462 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2463 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002464 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2465 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002466 _ASYNCIO_TASK_CANCEL_METHODDEF
2467 _ASYNCIO_TASK_GET_STACK_METHODDEF
2468 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002469 _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002470 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002471 _ASYNCIO_TASK_GET_NAME_METHODDEF
2472 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002473 _ASYNCIO_TASK_GET_CORO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002474 {"__class_getitem__", task_cls_getitem, METH_O|METH_CLASS, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002475 {NULL, NULL} /* Sentinel */
2476};
2477
2478static PyGetSetDef TaskType_getsetlist[] = {
2479 FUTURE_COMMON_GETSETLIST
2480 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2481 (setter)TaskObj_set_log_destroy_pending, NULL},
2482 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2483 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2484 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2485 {NULL} /* Sentinel */
2486};
2487
2488static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002489 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002490 "_asyncio.Task",
2491 sizeof(TaskObj), /* tp_basicsize */
2492 .tp_base = &FutureType,
2493 .tp_dealloc = TaskObj_dealloc,
2494 .tp_as_async = &FutureType_as_async,
2495 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002496 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002497 .tp_doc = _asyncio_Task___init____doc__,
2498 .tp_traverse = (traverseproc)TaskObj_traverse,
2499 .tp_clear = (inquiry)TaskObj_clear,
2500 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2501 .tp_iter = (getiterfunc)future_new_iter,
2502 .tp_methods = TaskType_methods,
2503 .tp_getset = TaskType_getsetlist,
2504 .tp_dictoffset = offsetof(TaskObj, dict),
2505 .tp_init = (initproc)_asyncio_Task___init__,
2506 .tp_new = PyType_GenericNew,
2507 .tp_finalize = (destructor)TaskObj_finalize,
2508};
2509
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002510static void
2511TaskObj_dealloc(PyObject *self)
2512{
2513 TaskObj *task = (TaskObj *)self;
2514
2515 if (Task_CheckExact(self)) {
2516 /* When fut is subclass of Task, finalizer is called from
2517 * subtype_dealloc.
2518 */
2519 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2520 // resurrected.
2521 return;
2522 }
2523 }
2524
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002525 PyObject_GC_UnTrack(self);
2526
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002527 if (task->task_weakreflist != NULL) {
2528 PyObject_ClearWeakRefs(self);
2529 }
2530
2531 (void)TaskObj_clear(task);
2532 Py_TYPE(task)->tp_free(task);
2533}
2534
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002535static int
2536task_call_step_soon(TaskObj *task, PyObject *arg)
2537{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002538 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002539 if (cb == NULL) {
2540 return -1;
2541 }
2542
Yury Selivanovf23746a2018-01-22 19:11:18 -05002543 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002544 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002545 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002546}
2547
2548static PyObject *
2549task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2550{
2551 PyObject* msg;
2552
2553 va_list vargs;
2554#ifdef HAVE_STDARG_PROTOTYPES
2555 va_start(vargs, format);
2556#else
2557 va_start(vargs);
2558#endif
2559 msg = PyUnicode_FromFormatV(format, vargs);
2560 va_end(vargs);
2561
2562 if (msg == NULL) {
2563 return NULL;
2564 }
2565
Petr Viktorinffd97532020-02-11 17:46:57 +01002566 PyObject *e = PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002567 Py_DECREF(msg);
2568 if (e == NULL) {
2569 return NULL;
2570 }
2571
2572 if (task_call_step_soon(task, e) == -1) {
2573 Py_DECREF(e);
2574 return NULL;
2575 }
2576
2577 Py_DECREF(e);
2578 Py_RETURN_NONE;
2579}
2580
Vladimir Matveev2b053612020-09-18 18:38:38 -07002581static inline int
2582gen_status_from_result(PyObject **result)
2583{
2584 if (*result != NULL) {
2585 return PYGEN_NEXT;
2586 }
2587 if (_PyGen_FetchStopIterationValue(result) == 0) {
2588 return PYGEN_RETURN;
2589 }
2590
2591 assert(PyErr_Occurred());
2592 return PYGEN_ERROR;
2593}
2594
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002595static PyObject *
2596task_step_impl(TaskObj *task, PyObject *exc)
2597{
2598 int res;
2599 int clear_exc = 0;
2600 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002601 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002602 PyObject *o;
2603
2604 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002605 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002606 "_step(): already done: %R %R",
2607 task,
2608 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002609 goto fail;
2610 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002611
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002612 if (task->task_must_cancel) {
2613 assert(exc != Py_None);
2614
2615 if (exc) {
2616 /* Check if exc is a CancelledError */
2617 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2618 if (res == -1) {
2619 /* An error occurred, abort */
2620 goto fail;
2621 }
2622 if (res == 0) {
2623 /* exc is not CancelledError; reset it to NULL */
2624 exc = NULL;
2625 }
2626 }
2627
2628 if (!exc) {
2629 /* exc was not a CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002630 exc = create_cancelled_error(task->task_cancel_msg);
2631
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002632 if (!exc) {
2633 goto fail;
2634 }
2635 clear_exc = 1;
2636 }
2637
2638 task->task_must_cancel = 0;
2639 }
2640
2641 Py_CLEAR(task->task_fut_waiter);
2642
Serhiy Storchakabca49392017-09-03 08:10:14 +03002643 coro = task->task_coro;
2644 if (coro == NULL) {
2645 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
Chris Jerdonekd2c349b2020-05-08 03:54:38 -07002646 if (clear_exc) {
2647 /* We created 'exc' during this call */
2648 Py_DECREF(exc);
2649 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002650 return NULL;
2651 }
2652
Vladimir Matveev2b053612020-09-18 18:38:38 -07002653 int gen_status = PYGEN_ERROR;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002654 if (exc == NULL) {
Vladimir Matveev037245c2020-10-09 17:15:15 -07002655 gen_status = PyIter_Send(coro, Py_None, &result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002656 }
2657 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002658 result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
Vladimir Matveev2b053612020-09-18 18:38:38 -07002659 gen_status = gen_status_from_result(&result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002660 if (clear_exc) {
2661 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002662 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002663 }
2664 }
2665
Vladimir Matveev2b053612020-09-18 18:38:38 -07002666 if (gen_status == PYGEN_RETURN || gen_status == PYGEN_ERROR) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002667 PyObject *et, *ev, *tb;
2668
Vladimir Matveev2b053612020-09-18 18:38:38 -07002669 if (result != NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002670 /* The error is StopIteration and that means that
2671 the underlying coroutine has resolved */
Yury Selivanovedad4d82019-09-25 03:32:08 -07002672
2673 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002674 if (task->task_must_cancel) {
2675 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002676 task->task_must_cancel = 0;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002677 res = future_cancel((FutureObj*)task, task->task_cancel_msg);
INADA Naoki991adca2017-05-11 21:18:38 +09002678 }
Yury Selivanovedad4d82019-09-25 03:32:08 -07002679 else {
Vladimir Matveev2b053612020-09-18 18:38:38 -07002680 res = future_set_result((FutureObj*)task, result);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002681 }
2682
Vladimir Matveev2b053612020-09-18 18:38:38 -07002683 Py_DECREF(result);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002684
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002685 if (res == NULL) {
2686 return NULL;
2687 }
2688 Py_DECREF(res);
2689 Py_RETURN_NONE;
2690 }
2691
2692 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2693 /* CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002694 PyErr_Fetch(&et, &ev, &tb);
2695
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002696 FutureObj *fut = (FutureObj*)task;
2697 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
2698 exc_state->exc_type = et;
2699 exc_state->exc_value = ev;
2700 exc_state->exc_traceback = tb;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002701
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002702 return future_cancel(fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002703 }
2704
2705 /* Some other exception; pop it and call Task.set_exception() */
2706 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002707
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002708 assert(et);
2709 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2710 PyErr_NormalizeException(&et, &ev, &tb);
2711 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002712 if (tb != NULL) {
2713 PyException_SetTraceback(ev, tb);
2714 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002715 o = future_set_exception((FutureObj*)task, ev);
2716 if (!o) {
2717 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002718 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002719 Py_XDECREF(tb);
2720 Py_XDECREF(ev);
2721 goto fail;
2722 }
2723 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002724 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002725
Yury Selivanov431b5402019-05-27 14:45:12 +02002726 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2727 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2728 {
2729 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002730 PyErr_Restore(et, ev, tb);
2731 goto fail;
2732 }
2733
Serhiy Storchakabca49392017-09-03 08:10:14 +03002734 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002735 Py_XDECREF(tb);
2736 Py_XDECREF(ev);
2737
2738 Py_RETURN_NONE;
2739 }
2740
2741 if (result == (PyObject*)task) {
2742 /* We have a task that wants to await on itself */
2743 goto self_await;
2744 }
2745
2746 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2747 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2748 PyObject *wrapper;
2749 PyObject *res;
2750 FutureObj *fut = (FutureObj*)result;
2751
2752 /* Check if `result` future is attached to a different loop */
2753 if (fut->fut_loop != task->task_loop) {
2754 goto different_loop;
2755 }
2756
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002757 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002758 goto yield_insteadof_yf;
2759 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002760
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002761 fut->fut_blocking = 0;
2762
2763 /* result.add_done_callback(task._wakeup) */
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07002764 wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002765 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002766 goto fail;
2767 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002768 res = future_add_done_callback(
2769 (FutureObj*)result, wrapper, task->task_context);
2770 Py_DECREF(wrapper);
2771 if (res == NULL) {
2772 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002773 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002774 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002775
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002776 /* task._fut_waiter = result */
2777 task->task_fut_waiter = result; /* no incref is necessary */
2778
2779 if (task->task_must_cancel) {
2780 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002781 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002782 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2783 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002784 if (r == NULL) {
2785 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002786 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002787 is_true = PyObject_IsTrue(r);
2788 Py_DECREF(r);
2789 if (is_true < 0) {
2790 return NULL;
2791 }
2792 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002793 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002794 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002795 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002796
2797 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002798 }
2799
2800 /* Check if `result` is None */
2801 if (result == Py_None) {
2802 /* Bare yield relinquishes control for one event loop iteration. */
2803 if (task_call_step_soon(task, NULL)) {
2804 goto fail;
2805 }
2806 return result;
2807 }
2808
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002809 /* Check if `result` is a Future-compatible object */
2810 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2811 goto fail;
2812 }
2813 if (o != NULL && o != Py_None) {
2814 /* `result` is a Future-compatible object */
2815 PyObject *wrapper;
2816 PyObject *res;
2817
2818 int blocking = PyObject_IsTrue(o);
2819 Py_DECREF(o);
2820 if (blocking < 0) {
2821 goto fail;
2822 }
2823
2824 /* Check if `result` future is attached to a different loop */
2825 PyObject *oloop = get_future_loop(result);
2826 if (oloop == NULL) {
2827 goto fail;
2828 }
2829 if (oloop != task->task_loop) {
2830 Py_DECREF(oloop);
2831 goto different_loop;
2832 }
2833 Py_DECREF(oloop);
2834
2835 if (!blocking) {
2836 goto yield_insteadof_yf;
2837 }
2838
2839 /* result._asyncio_future_blocking = False */
2840 if (_PyObject_SetAttrId(
2841 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2842 goto fail;
2843 }
2844
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07002845 wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002846 if (wrapper == NULL) {
2847 goto fail;
2848 }
2849
2850 /* result.add_done_callback(task._wakeup) */
2851 PyObject *add_cb = _PyObject_GetAttrId(
2852 result, &PyId_add_done_callback);
2853 if (add_cb == NULL) {
2854 Py_DECREF(wrapper);
2855 goto fail;
2856 }
2857 PyObject *stack[2];
2858 stack[0] = wrapper;
2859 stack[1] = (PyObject *)task->task_context;
Petr Viktorinffd97532020-02-11 17:46:57 +01002860 res = PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002861 Py_DECREF(add_cb);
2862 Py_DECREF(wrapper);
2863 if (res == NULL) {
2864 goto fail;
2865 }
2866 Py_DECREF(res);
2867
2868 /* task._fut_waiter = result */
2869 task->task_fut_waiter = result; /* no incref is necessary */
2870
2871 if (task->task_must_cancel) {
2872 PyObject *r;
2873 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002874 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2875 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002876 if (r == NULL) {
2877 return NULL;
2878 }
2879 is_true = PyObject_IsTrue(r);
2880 Py_DECREF(r);
2881 if (is_true < 0) {
2882 return NULL;
2883 }
2884 else if (is_true) {
2885 task->task_must_cancel = 0;
2886 }
2887 }
2888
2889 Py_RETURN_NONE;
2890 }
2891
2892 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002893 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002894 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2895 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002896 goto fail;
2897 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002898 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002899 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002900 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002901 task, PyExc_RuntimeError,
2902 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002903 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002904 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002905 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002906 }
2907
2908 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002909 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002910 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002911 Py_DECREF(result);
2912 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002913
2914self_await:
2915 o = task_set_error_soon(
2916 task, PyExc_RuntimeError,
2917 "Task cannot await on itself: %R", task);
2918 Py_DECREF(result);
2919 return o;
2920
2921yield_insteadof_yf:
2922 o = task_set_error_soon(
2923 task, PyExc_RuntimeError,
2924 "yield was used instead of yield from "
2925 "in task %R with %R",
2926 task, result);
2927 Py_DECREF(result);
2928 return o;
2929
2930different_loop:
2931 o = task_set_error_soon(
2932 task, PyExc_RuntimeError,
2933 "Task %R got Future %R attached to a different loop",
2934 task, result);
2935 Py_DECREF(result);
2936 return o;
2937
2938fail:
2939 Py_XDECREF(result);
2940 return NULL;
2941}
2942
2943static PyObject *
2944task_step(TaskObj *task, PyObject *exc)
2945{
2946 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002947
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002948 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002949 return NULL;
2950 }
2951
2952 res = task_step_impl(task, exc);
2953
2954 if (res == NULL) {
2955 PyObject *et, *ev, *tb;
2956 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002957 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002958 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002959 return NULL;
2960 }
2961 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002962 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002963 Py_DECREF(res);
2964 return NULL;
2965 }
2966 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002967 return res;
2968 }
2969 }
2970}
2971
2972static PyObject *
2973task_wakeup(TaskObj *task, PyObject *o)
2974{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002975 PyObject *et, *ev, *tb;
2976 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002977 assert(o);
2978
2979 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2980 PyObject *fut_result = NULL;
2981 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002982
2983 switch(res) {
2984 case -1:
2985 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002986 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002987 case 0:
2988 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002989 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002990 default:
2991 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002992 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002993 Py_DECREF(fut_result);
2994 return result;
2995 }
2996 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002997 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002998 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2999 if (fut_result != NULL) {
3000 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003001 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003002 }
3003 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003004 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003005
3006 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003007 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
3008 PyErr_NormalizeException(&et, &ev, &tb);
3009 }
3010
Yury Selivanov22feeb82018-01-24 11:31:01 -05003011 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003012
3013 Py_DECREF(et);
3014 Py_XDECREF(tb);
3015 Py_XDECREF(ev);
3016
3017 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003018}
3019
3020
Yury Selivanova70232f2017-12-13 14:49:42 -05003021/*********************** Functions **************************/
3022
3023
3024/*[clinic input]
3025_asyncio._get_running_loop
3026
3027Return the running event loop or None.
3028
3029This is a low-level function intended to be used by event loops.
3030This function is thread-specific.
3031
3032[clinic start generated code]*/
3033
3034static PyObject *
3035_asyncio__get_running_loop_impl(PyObject *module)
3036/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3037{
3038 PyObject *loop;
3039 if (get_running_loop(&loop)) {
3040 return NULL;
3041 }
3042 if (loop == NULL) {
3043 /* There's no currently running event loop */
3044 Py_RETURN_NONE;
3045 }
3046 return loop;
3047}
3048
3049/*[clinic input]
3050_asyncio._set_running_loop
3051 loop: 'O'
3052 /
3053
3054Set the running event loop.
3055
3056This is a low-level function intended to be used by event loops.
3057This function is thread-specific.
3058[clinic start generated code]*/
3059
3060static PyObject *
3061_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3062/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3063{
3064 if (set_running_loop(loop)) {
3065 return NULL;
3066 }
3067 Py_RETURN_NONE;
3068}
3069
3070/*[clinic input]
3071_asyncio.get_event_loop
3072
3073Return an asyncio event loop.
3074
3075When called from a coroutine or a callback (e.g. scheduled with
3076call_soon or similar API), this function will always return the
3077running event loop.
3078
3079If there is no running event loop set, the function will return
3080the result of `get_event_loop_policy().get_event_loop()` call.
3081[clinic start generated code]*/
3082
3083static PyObject *
3084_asyncio_get_event_loop_impl(PyObject *module)
3085/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3086{
Serhiy Storchaka172c0f22021-04-25 13:40:44 +03003087 return get_event_loop(1);
3088}
3089
3090/*[clinic input]
3091_asyncio._get_event_loop
3092 stacklevel: int = 3
3093[clinic start generated code]*/
3094
3095static PyObject *
3096_asyncio__get_event_loop_impl(PyObject *module, int stacklevel)
3097/*[clinic end generated code: output=9c1d6d3c802e67c9 input=d17aebbd686f711d]*/
3098{
3099 return get_event_loop(stacklevel-1);
Yury Selivanova70232f2017-12-13 14:49:42 -05003100}
3101
3102/*[clinic input]
3103_asyncio.get_running_loop
3104
3105Return the running event loop. Raise a RuntimeError if there is none.
3106
3107This function is thread-specific.
3108[clinic start generated code]*/
3109
3110static PyObject *
3111_asyncio_get_running_loop_impl(PyObject *module)
3112/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3113{
3114 PyObject *loop;
3115 if (get_running_loop(&loop)) {
3116 return NULL;
3117 }
3118 if (loop == NULL) {
3119 /* There's no currently running event loop */
3120 PyErr_SetString(
3121 PyExc_RuntimeError, "no running event loop");
3122 }
3123 return loop;
3124}
3125
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003126/*[clinic input]
3127_asyncio._register_task
3128
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003129 task: object
3130
3131Register a new task in asyncio as executed by loop.
3132
3133Returns None.
3134[clinic start generated code]*/
3135
3136static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003137_asyncio__register_task_impl(PyObject *module, PyObject *task)
3138/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003139{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003140 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003141 return NULL;
3142 }
3143 Py_RETURN_NONE;
3144}
3145
3146
3147/*[clinic input]
3148_asyncio._unregister_task
3149
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003150 task: object
3151
3152Unregister a task.
3153
3154Returns None.
3155[clinic start generated code]*/
3156
3157static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003158_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3159/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003160{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003161 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003162 return NULL;
3163 }
3164 Py_RETURN_NONE;
3165}
3166
3167
3168/*[clinic input]
3169_asyncio._enter_task
3170
3171 loop: object
3172 task: object
3173
3174Enter into task execution or resume suspended task.
3175
3176Task belongs to loop.
3177
3178Returns None.
3179[clinic start generated code]*/
3180
3181static PyObject *
3182_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3183/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3184{
3185 if (enter_task(loop, task) < 0) {
3186 return NULL;
3187 }
3188 Py_RETURN_NONE;
3189}
3190
3191
3192/*[clinic input]
3193_asyncio._leave_task
3194
3195 loop: object
3196 task: object
3197
3198Leave task execution or suspend a task.
3199
3200Task belongs to loop.
3201
3202Returns None.
3203[clinic start generated code]*/
3204
3205static PyObject *
3206_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3207/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3208{
3209 if (leave_task(loop, task) < 0) {
3210 return NULL;
3211 }
3212 Py_RETURN_NONE;
3213}
3214
Yury Selivanova70232f2017-12-13 14:49:42 -05003215
Yury Selivanov9d411c12018-01-23 15:10:03 -05003216/*********************** PyRunningLoopHolder ********************/
3217
3218
3219static PyRunningLoopHolder *
3220new_running_loop_holder(PyObject *loop)
3221{
3222 PyRunningLoopHolder *rl = PyObject_New(
3223 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3224 if (rl == NULL) {
3225 return NULL;
3226 }
3227
3228#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3229 rl->rl_pid = getpid();
3230#endif
3231
3232 Py_INCREF(loop);
3233 rl->rl_loop = loop;
3234
3235 return rl;
3236}
3237
3238
3239static void
3240PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3241{
Miss Islington (bot)6846d672021-10-08 01:55:41 -07003242 if (cached_running_holder == (PyObject *)rl) {
3243 cached_running_holder = NULL;
3244 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003245 Py_CLEAR(rl->rl_loop);
3246 PyObject_Free(rl);
3247}
3248
3249
3250static PyTypeObject PyRunningLoopHolder_Type = {
3251 PyVarObject_HEAD_INIT(NULL, 0)
3252 "_RunningLoopHolder",
3253 sizeof(PyRunningLoopHolder),
3254 .tp_getattro = PyObject_GenericGetAttr,
3255 .tp_flags = Py_TPFLAGS_DEFAULT,
3256 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3257};
3258
3259
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003260/*********************** Module **************************/
3261
3262
3263static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003264module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003265{
3266 PyObject *next;
3267 PyObject *current;
3268
3269 next = (PyObject*) fi_freelist;
3270 while (next != NULL) {
3271 assert(fi_freelist_len > 0);
3272 fi_freelist_len--;
3273
3274 current = next;
3275 next = (PyObject*) ((futureiterobject*) current)->future;
3276 PyObject_GC_Del(current);
3277 }
3278 assert(fi_freelist_len == 0);
3279 fi_freelist = NULL;
3280}
3281
3282
3283static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003284module_free(void *m)
3285{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003286 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003287 Py_CLEAR(traceback_extract_stack);
3288 Py_CLEAR(asyncio_future_repr_info_func);
3289 Py_CLEAR(asyncio_get_event_loop_policy);
3290 Py_CLEAR(asyncio_iscoroutine_func);
3291 Py_CLEAR(asyncio_task_get_stack_func);
3292 Py_CLEAR(asyncio_task_print_stack_func);
3293 Py_CLEAR(asyncio_task_repr_info_func);
3294 Py_CLEAR(asyncio_InvalidStateError);
3295 Py_CLEAR(asyncio_CancelledError);
3296
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003297 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003298 Py_CLEAR(current_tasks);
3299 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003300
Yury Selivanovf23746a2018-01-22 19:11:18 -05003301 Py_CLEAR(context_kwname);
3302
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003303 module_free_freelists();
Jeffrey Quesnellea75e7302020-04-16 22:09:45 -04003304
3305 module_initialized = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003306}
3307
3308static int
3309module_init(void)
3310{
3311 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003312
3313 asyncio_mod = PyImport_ImportModule("asyncio");
3314 if (asyncio_mod == NULL) {
3315 goto fail;
3316 }
Ben Harper321def82019-10-07 12:19:58 -04003317 if (module_initialized != 0) {
3318 return 0;
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02003319 }
Ben Harper321def82019-10-07 12:19:58 -04003320 else {
3321 module_initialized = 1;
3322 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003323
3324 current_tasks = PyDict_New();
3325 if (current_tasks == NULL) {
3326 goto fail;
3327 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003328
Yury Selivanova9d7e552017-12-19 07:18:45 -05003329 iscoroutine_typecache = PySet_New(NULL);
3330 if (iscoroutine_typecache == NULL) {
3331 goto fail;
3332 }
3333
Yury Selivanovf23746a2018-01-22 19:11:18 -05003334
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003335 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003336 if (context_kwname == NULL) {
3337 goto fail;
3338 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003339
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003340#define WITH_MOD(NAME) \
3341 Py_CLEAR(module); \
3342 module = PyImport_ImportModule(NAME); \
3343 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003344 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003345 }
3346
3347#define GET_MOD_ATTR(VAR, NAME) \
3348 VAR = PyObject_GetAttrString(module, NAME); \
3349 if (VAR == NULL) { \
3350 goto fail; \
3351 }
3352
3353 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003354 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003355
3356 WITH_MOD("asyncio.base_futures")
3357 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003358
3359 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003360 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3361 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3362
3363 WITH_MOD("asyncio.base_tasks")
3364 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3365 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3366 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3367
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003368 WITH_MOD("asyncio.coroutines")
3369 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3370
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003371 WITH_MOD("traceback")
3372 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3373
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003374 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003375 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003376 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003377 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003378 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003379 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003380 goto fail;
3381 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003382
Serhiy Storchakabca49392017-09-03 08:10:14 +03003383 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003384 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003385
INADA Naokic411a7d2016-10-18 11:48:14 +09003386fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003387 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003388 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003389 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003390
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003391#undef WITH_MOD
3392#undef GET_MOD_ATTR
3393}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003394
INADA Naokic411a7d2016-10-18 11:48:14 +09003395PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003396
Yury Selivanova70232f2017-12-13 14:49:42 -05003397static PyMethodDef asyncio_methods[] = {
3398 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
Serhiy Storchaka172c0f22021-04-25 13:40:44 +03003399 _ASYNCIO__GET_EVENT_LOOP_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003400 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3401 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3402 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003403 _ASYNCIO__REGISTER_TASK_METHODDEF
3404 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3405 _ASYNCIO__ENTER_TASK_METHODDEF
3406 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003407 {NULL, NULL}
3408};
3409
INADA Naoki9f2ce252016-10-15 15:39:19 +09003410static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003411 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003412 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003413 module_doc, /* m_doc */
3414 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003415 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003416 NULL, /* m_slots */
3417 NULL, /* m_traverse */
3418 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003419 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003420};
3421
3422
3423PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003424PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003425{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003426 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003427 return NULL;
3428 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003429 if (PyType_Ready(&FutureIterType) < 0) {
3430 return NULL;
3431 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003432 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003433 return NULL;
3434 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003435 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3436 return NULL;
3437 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003438
INADA Naoki9f2ce252016-10-15 15:39:19 +09003439 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003440 if (m == NULL) {
3441 return NULL;
3442 }
3443
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003444 /* FutureType and TaskType are made ready by PyModule_AddType() calls below. */
3445 if (PyModule_AddType(m, &FutureType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003446 Py_DECREF(m);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003447 return NULL;
3448 }
3449
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003450 if (PyModule_AddType(m, &TaskType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003451 Py_DECREF(m);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003452 return NULL;
3453 }
3454
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003455 Py_INCREF(all_tasks);
3456 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3457 Py_DECREF(all_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003458 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003459 return NULL;
3460 }
3461
3462 Py_INCREF(current_tasks);
3463 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3464 Py_DECREF(current_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003465 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003466 return NULL;
3467 }
3468
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003469 return m;
3470}