blob: a4d5d4551e9b0af08ef10b10dc775be78650260e [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,
Vladimir Matveev1e996c32020-11-10 12:09:55 -08001767 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1768 Py_TPFLAGS_HAVE_AM_SEND,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001769 .tp_traverse = (traverseproc)FutureIter_traverse,
1770 .tp_iter = PyObject_SelfIter,
1771 .tp_iternext = (iternextfunc)FutureIter_iternext,
1772 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001773};
1774
1775static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001776future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001777{
1778 futureiterobject *it;
1779
1780 if (!PyObject_TypeCheck(fut, &FutureType)) {
1781 PyErr_BadInternalCall();
1782 return NULL;
1783 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001784
1785 ENSURE_FUTURE_ALIVE(fut)
1786
1787 if (fi_freelist_len) {
1788 fi_freelist_len--;
1789 it = fi_freelist;
1790 fi_freelist = (futureiterobject*) it->future;
1791 it->future = NULL;
1792 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001793 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001794 else {
1795 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1796 if (it == NULL) {
1797 return NULL;
1798 }
1799 }
1800
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001801 Py_INCREF(fut);
1802 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001803 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001804 return (PyObject*)it;
1805}
1806
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001807
1808/*********************** Task **************************/
1809
1810
1811/*[clinic input]
1812class _asyncio.Task "TaskObj *" "&Task_Type"
1813[clinic start generated code]*/
1814/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1815
1816static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001817static PyObject * task_wakeup(TaskObj *, PyObject *);
1818static PyObject * task_step(TaskObj *, PyObject *);
1819
1820/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001821
INADA Naokic411a7d2016-10-18 11:48:14 +09001822static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001823TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001824{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001825 Py_CLEAR(o->sw_task);
1826 Py_CLEAR(o->sw_arg);
1827 return 0;
1828}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001829
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001830static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001831TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001832{
1833 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001834 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001835 Py_TYPE(o)->tp_free(o);
1836}
1837
1838static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001839TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001840 PyObject *args, PyObject *kwds)
1841{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001842 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1843 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1844 return NULL;
1845 }
1846 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1847 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1848 return NULL;
1849 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001850 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001851}
1852
1853static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001854TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001855 visitproc visit, void *arg)
1856{
1857 Py_VISIT(o->sw_task);
1858 Py_VISIT(o->sw_arg);
1859 return 0;
1860}
1861
1862static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001863TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001864{
1865 if (o->sw_task) {
1866 Py_INCREF(o->sw_task);
1867 return (PyObject*)o->sw_task;
1868 }
1869 Py_RETURN_NONE;
1870}
1871
Serhiy Storchakabca49392017-09-03 08:10:14 +03001872static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1873 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001874 {NULL} /* Sentinel */
1875};
1876
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001877static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001878 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001879 "TaskStepMethWrapper",
1880 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001881 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001882 .tp_getset = TaskStepMethWrapper_getsetlist,
1883 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1884 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001885 .tp_getattro = PyObject_GenericGetAttr,
1886 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001887 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1888 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001889};
1890
1891static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001892TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001893{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001894 TaskStepMethWrapper *o;
1895 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001896 if (o == NULL) {
1897 return NULL;
1898 }
1899
1900 Py_INCREF(task);
1901 o->sw_task = task;
1902
1903 Py_XINCREF(arg);
1904 o->sw_arg = arg;
1905
1906 PyObject_GC_Track(o);
1907 return (PyObject*) o;
1908}
1909
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07001910/* ----- Task._wakeup implementation */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001911
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07001912static PyMethodDef TaskWakeupDef = {
1913 "task_wakeup",
1914 (PyCFunction)task_wakeup,
1915 METH_O,
1916 NULL
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001917};
1918
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001919/* ----- Task introspection helpers */
1920
1921static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001922register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001923{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001924 _Py_IDENTIFIER(add);
1925
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001926 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1927 &PyId_add, task);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001928 if (res == NULL) {
1929 return -1;
1930 }
1931 Py_DECREF(res);
1932 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001933}
1934
1935
1936static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001937unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001938{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001939 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001940
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001941 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1942 &PyId_discard, task);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001943 if (res == NULL) {
1944 return -1;
1945 }
1946 Py_DECREF(res);
1947 return 0;
1948}
1949
1950
1951static int
1952enter_task(PyObject *loop, PyObject *task)
1953{
1954 PyObject *item;
1955 Py_hash_t hash;
1956 hash = PyObject_Hash(loop);
1957 if (hash == -1) {
1958 return -1;
1959 }
1960 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1961 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001962 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001963 PyErr_Format(
1964 PyExc_RuntimeError,
1965 "Cannot enter into task %R while another " \
1966 "task %R is being executed.",
1967 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03001968 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001969 return -1;
1970 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001971 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001972 return -1;
1973 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03001974 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001975}
1976
1977
1978static int
1979leave_task(PyObject *loop, PyObject *task)
1980/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
1981{
1982 PyObject *item;
1983 Py_hash_t hash;
1984 hash = PyObject_Hash(loop);
1985 if (hash == -1) {
1986 return -1;
1987 }
1988 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1989 if (item != task) {
1990 if (item == NULL) {
1991 /* Not entered, replace with None */
1992 item = Py_None;
1993 }
1994 PyErr_Format(
1995 PyExc_RuntimeError,
1996 "Leaving task %R does not match the current task %R.",
1997 task, item, NULL);
1998 return -1;
1999 }
2000 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
2001}
2002
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002003/* ----- Task */
2004
2005/*[clinic input]
2006_asyncio.Task.__init__
2007
Serhiy Storchakabca49392017-09-03 08:10:14 +03002008 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002009 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002010 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002011 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002012
2013A coroutine wrapped in a Future.
2014[clinic start generated code]*/
2015
2016static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002017_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2018 PyObject *name)
2019/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002020{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002021 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002022 return -1;
2023 }
INADA Naokic411a7d2016-10-18 11:48:14 +09002024
Yury Selivanova9d7e552017-12-19 07:18:45 -05002025 int is_coro = is_coroutine(coro);
2026 if (is_coro == -1) {
2027 return -1;
2028 }
2029 if (is_coro == 0) {
2030 self->task_log_destroy_pending = 0;
2031 PyErr_Format(PyExc_TypeError,
2032 "a coroutine was expected, got %R",
2033 coro, NULL);
2034 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02002035 }
2036
Oren Milmand019bc82018-02-13 12:28:33 +02002037 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05002038 if (self->task_context == NULL) {
2039 return -1;
2040 }
2041
Oren Milmand019bc82018-02-13 12:28:33 +02002042 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002043 self->task_must_cancel = 0;
2044 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002045 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02002046 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002047
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002048 if (name == Py_None) {
2049 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03002050 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002051 name = PyObject_Str(name);
2052 } else {
2053 Py_INCREF(name);
2054 }
2055 Py_XSETREF(self->task_name, name);
2056 if (self->task_name == NULL) {
2057 return -1;
2058 }
2059
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002060 if (task_call_step_soon(self, NULL)) {
2061 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09002062 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002063 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002064}
2065
2066static int
2067TaskObj_clear(TaskObj *task)
2068{
2069 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002070 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002071 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002072 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002073 Py_CLEAR(task->task_fut_waiter);
2074 return 0;
2075}
2076
2077static int
2078TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2079{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002080 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002081 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002082 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002083 Py_VISIT(task->task_fut_waiter);
2084 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2085 return 0;
2086}
2087
2088static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002089TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002090{
2091 if (task->task_log_destroy_pending) {
2092 Py_RETURN_TRUE;
2093 }
2094 else {
2095 Py_RETURN_FALSE;
2096 }
2097}
2098
2099static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002100TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002101{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002102 if (val == NULL) {
2103 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2104 return -1;
2105 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002106 int is_true = PyObject_IsTrue(val);
2107 if (is_true < 0) {
2108 return -1;
2109 }
2110 task->task_log_destroy_pending = is_true;
2111 return 0;
2112}
2113
2114static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002115TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002116{
2117 if (task->task_must_cancel) {
2118 Py_RETURN_TRUE;
2119 }
2120 else {
2121 Py_RETURN_FALSE;
2122 }
2123}
2124
2125static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002126TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002127{
2128 if (task->task_coro) {
2129 Py_INCREF(task->task_coro);
2130 return task->task_coro;
2131 }
2132
2133 Py_RETURN_NONE;
2134}
2135
2136static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002137TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002138{
2139 if (task->task_fut_waiter) {
2140 Py_INCREF(task->task_fut_waiter);
2141 return task->task_fut_waiter;
2142 }
2143
2144 Py_RETURN_NONE;
2145}
2146
2147/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002148_asyncio.Task._make_cancelled_error
2149
2150Create the CancelledError to raise if the Task is cancelled.
2151
2152This should only be called once when handling a cancellation since
2153it erases the context exception value.
2154[clinic start generated code]*/
2155
2156static PyObject *
2157_asyncio_Task__make_cancelled_error_impl(TaskObj *self)
2158/*[clinic end generated code: output=55a819e8b4276fab input=52c0e32de8e2f840]*/
2159{
2160 FutureObj *fut = (FutureObj*)self;
2161 return _asyncio_Future__make_cancelled_error_impl(fut);
2162}
2163
2164
2165/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002166_asyncio.Task._repr_info
2167[clinic start generated code]*/
2168
2169static PyObject *
2170_asyncio_Task__repr_info_impl(TaskObj *self)
2171/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2172{
Petr Viktorinffd97532020-02-11 17:46:57 +01002173 return PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002174}
2175
2176/*[clinic input]
2177_asyncio.Task.cancel
2178
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002179 msg: object = None
2180
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002181Request that this task cancel itself.
2182
2183This arranges for a CancelledError to be thrown into the
2184wrapped coroutine on the next cycle through the event loop.
2185The coroutine then has a chance to clean up or even deny
2186the request using try/except/finally.
2187
2188Unlike Future.cancel, this does not guarantee that the
2189task will be cancelled: the exception might be caught and
2190acted upon, delaying cancellation of the task or preventing
2191cancellation completely. The task may also return a value or
2192raise a different exception.
2193
2194Immediately after this method is called, Task.cancelled() will
2195not return True (unless the task was already cancelled). A
2196task will be marked as cancelled when the wrapped coroutine
2197terminates with a CancelledError exception (even if cancel()
2198was not called).
2199[clinic start generated code]*/
2200
2201static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002202_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
2203/*[clinic end generated code: output=c66b60d41c74f9f1 input=f4ff8e8ffc5f1c00]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002204{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002205 self->task_log_tb = 0;
2206
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002207 if (self->task_state != STATE_PENDING) {
2208 Py_RETURN_FALSE;
2209 }
2210
2211 if (self->task_fut_waiter) {
2212 PyObject *res;
2213 int is_true;
2214
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002215 res = _PyObject_CallMethodIdOneArg(self->task_fut_waiter,
2216 &PyId_cancel, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002217 if (res == NULL) {
2218 return NULL;
2219 }
2220
2221 is_true = PyObject_IsTrue(res);
2222 Py_DECREF(res);
2223 if (is_true < 0) {
2224 return NULL;
2225 }
2226
2227 if (is_true) {
2228 Py_RETURN_TRUE;
2229 }
2230 }
2231
2232 self->task_must_cancel = 1;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002233 Py_XINCREF(msg);
2234 Py_XSETREF(self->task_cancel_msg, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002235 Py_RETURN_TRUE;
2236}
2237
2238/*[clinic input]
2239_asyncio.Task.get_stack
2240
2241 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002242 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002243
2244Return the list of stack frames for this task's coroutine.
2245
2246If the coroutine is not done, this returns the stack where it is
2247suspended. If the coroutine has completed successfully or was
2248cancelled, this returns an empty list. If the coroutine was
2249terminated by an exception, this returns the list of traceback
2250frames.
2251
2252The frames are always ordered from oldest to newest.
2253
2254The optional limit gives the maximum number of frames to
2255return; by default all available frames are returned. Its
2256meaning differs depending on whether a stack or a traceback is
2257returned: the newest frames of a stack are returned, but the
2258oldest frames of a traceback are returned. (This matches the
2259behavior of the traceback module.)
2260
2261For reasons beyond our control, only one stack frame is
2262returned for a suspended coroutine.
2263[clinic start generated code]*/
2264
2265static PyObject *
2266_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002267/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002268{
2269 return PyObject_CallFunctionObjArgs(
2270 asyncio_task_get_stack_func, self, limit, NULL);
2271}
2272
2273/*[clinic input]
2274_asyncio.Task.print_stack
2275
2276 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002277 limit: object = None
2278 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002279
2280Print the stack or traceback for this task's coroutine.
2281
2282This produces output similar to that of the traceback module,
2283for the frames retrieved by get_stack(). The limit argument
2284is passed to get_stack(). The file argument is an I/O stream
2285to which the output is written; by default output is written
2286to sys.stderr.
2287[clinic start generated code]*/
2288
2289static PyObject *
2290_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2291 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002292/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002293{
2294 return PyObject_CallFunctionObjArgs(
2295 asyncio_task_print_stack_func, self, limit, file, NULL);
2296}
2297
2298/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002299_asyncio.Task.set_result
2300
2301 result: object
2302 /
2303[clinic start generated code]*/
2304
2305static PyObject *
2306_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2307/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2308{
2309 PyErr_SetString(PyExc_RuntimeError,
2310 "Task does not support set_result operation");
2311 return NULL;
2312}
2313
2314/*[clinic input]
2315_asyncio.Task.set_exception
2316
2317 exception: object
2318 /
2319[clinic start generated code]*/
2320
2321static PyObject *
2322_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2323/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2324{
2325 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002326 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002327 return NULL;
2328}
2329
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002330/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002331_asyncio.Task.get_coro
2332[clinic start generated code]*/
2333
2334static PyObject *
2335_asyncio_Task_get_coro_impl(TaskObj *self)
2336/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2337{
2338 Py_INCREF(self->task_coro);
2339 return self->task_coro;
2340}
2341
2342/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002343_asyncio.Task.get_name
2344[clinic start generated code]*/
2345
2346static PyObject *
2347_asyncio_Task_get_name_impl(TaskObj *self)
2348/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2349{
2350 if (self->task_name) {
2351 Py_INCREF(self->task_name);
2352 return self->task_name;
2353 }
2354
2355 Py_RETURN_NONE;
2356}
2357
2358/*[clinic input]
2359_asyncio.Task.set_name
2360
2361 value: object
2362 /
2363[clinic start generated code]*/
2364
2365static PyObject *
2366_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2367/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2368{
Alex Grönholma7548232018-08-09 23:49:49 +03002369 if (!PyUnicode_CheckExact(value)) {
2370 value = PyObject_Str(value);
2371 if (value == NULL) {
2372 return NULL;
2373 }
2374 } else {
2375 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002376 }
2377
Alex Grönholma7548232018-08-09 23:49:49 +03002378 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002379 Py_RETURN_NONE;
2380}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002381
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002382static void
2383TaskObj_finalize(TaskObj *task)
2384{
2385 _Py_IDENTIFIER(call_exception_handler);
2386 _Py_IDENTIFIER(task);
2387 _Py_IDENTIFIER(message);
2388 _Py_IDENTIFIER(source_traceback);
2389
Serhiy Storchakabca49392017-09-03 08:10:14 +03002390 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002391 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002392 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002393 PyObject *error_type, *error_value, *error_traceback;
2394
2395 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2396 goto done;
2397 }
2398
2399 /* Save the current exception, if any. */
2400 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2401
2402 context = PyDict_New();
2403 if (context == NULL) {
2404 goto finally;
2405 }
2406
2407 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2408 if (message == NULL) {
2409 goto finally;
2410 }
2411
2412 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2413 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2414 {
2415 goto finally;
2416 }
2417
2418 if (task->task_source_tb != NULL) {
2419 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2420 task->task_source_tb) < 0)
2421 {
2422 goto finally;
2423 }
2424 }
2425
2426 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2427 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01002428 PyObject *res = PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002429 if (res == NULL) {
2430 PyErr_WriteUnraisable(func);
2431 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002432 else {
2433 Py_DECREF(res);
2434 }
2435 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002436 }
2437
2438finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002439 Py_XDECREF(context);
2440 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002441
2442 /* Restore the saved exception. */
2443 PyErr_Restore(error_type, error_value, error_traceback);
2444
2445done:
2446 FutureObj_finalize((FutureObj*)task);
2447}
2448
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002449static PyObject *
2450task_cls_getitem(PyObject *cls, PyObject *type)
2451{
2452 Py_INCREF(cls);
2453 return cls;
2454}
2455
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002456static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2457
2458static PyMethodDef TaskType_methods[] = {
2459 _ASYNCIO_FUTURE_RESULT_METHODDEF
2460 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002461 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2462 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2463 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2464 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002465 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2466 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002467 _ASYNCIO_TASK_CANCEL_METHODDEF
2468 _ASYNCIO_TASK_GET_STACK_METHODDEF
2469 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002470 _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002471 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002472 _ASYNCIO_TASK_GET_NAME_METHODDEF
2473 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002474 _ASYNCIO_TASK_GET_CORO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002475 {"__class_getitem__", task_cls_getitem, METH_O|METH_CLASS, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002476 {NULL, NULL} /* Sentinel */
2477};
2478
2479static PyGetSetDef TaskType_getsetlist[] = {
2480 FUTURE_COMMON_GETSETLIST
2481 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2482 (setter)TaskObj_set_log_destroy_pending, NULL},
2483 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2484 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2485 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2486 {NULL} /* Sentinel */
2487};
2488
2489static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002490 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002491 "_asyncio.Task",
2492 sizeof(TaskObj), /* tp_basicsize */
2493 .tp_base = &FutureType,
2494 .tp_dealloc = TaskObj_dealloc,
2495 .tp_as_async = &FutureType_as_async,
2496 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002497 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002498 .tp_doc = _asyncio_Task___init____doc__,
2499 .tp_traverse = (traverseproc)TaskObj_traverse,
2500 .tp_clear = (inquiry)TaskObj_clear,
2501 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2502 .tp_iter = (getiterfunc)future_new_iter,
2503 .tp_methods = TaskType_methods,
2504 .tp_getset = TaskType_getsetlist,
2505 .tp_dictoffset = offsetof(TaskObj, dict),
2506 .tp_init = (initproc)_asyncio_Task___init__,
2507 .tp_new = PyType_GenericNew,
2508 .tp_finalize = (destructor)TaskObj_finalize,
2509};
2510
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002511static void
2512TaskObj_dealloc(PyObject *self)
2513{
2514 TaskObj *task = (TaskObj *)self;
2515
2516 if (Task_CheckExact(self)) {
2517 /* When fut is subclass of Task, finalizer is called from
2518 * subtype_dealloc.
2519 */
2520 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2521 // resurrected.
2522 return;
2523 }
2524 }
2525
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002526 PyObject_GC_UnTrack(self);
2527
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002528 if (task->task_weakreflist != NULL) {
2529 PyObject_ClearWeakRefs(self);
2530 }
2531
2532 (void)TaskObj_clear(task);
2533 Py_TYPE(task)->tp_free(task);
2534}
2535
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002536static int
2537task_call_step_soon(TaskObj *task, PyObject *arg)
2538{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002539 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002540 if (cb == NULL) {
2541 return -1;
2542 }
2543
Yury Selivanovf23746a2018-01-22 19:11:18 -05002544 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002545 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002546 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002547}
2548
2549static PyObject *
2550task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2551{
2552 PyObject* msg;
2553
2554 va_list vargs;
2555#ifdef HAVE_STDARG_PROTOTYPES
2556 va_start(vargs, format);
2557#else
2558 va_start(vargs);
2559#endif
2560 msg = PyUnicode_FromFormatV(format, vargs);
2561 va_end(vargs);
2562
2563 if (msg == NULL) {
2564 return NULL;
2565 }
2566
Petr Viktorinffd97532020-02-11 17:46:57 +01002567 PyObject *e = PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002568 Py_DECREF(msg);
2569 if (e == NULL) {
2570 return NULL;
2571 }
2572
2573 if (task_call_step_soon(task, e) == -1) {
2574 Py_DECREF(e);
2575 return NULL;
2576 }
2577
2578 Py_DECREF(e);
2579 Py_RETURN_NONE;
2580}
2581
Vladimir Matveev2b053612020-09-18 18:38:38 -07002582static inline int
2583gen_status_from_result(PyObject **result)
2584{
2585 if (*result != NULL) {
2586 return PYGEN_NEXT;
2587 }
2588 if (_PyGen_FetchStopIterationValue(result) == 0) {
2589 return PYGEN_RETURN;
2590 }
2591
2592 assert(PyErr_Occurred());
2593 return PYGEN_ERROR;
2594}
2595
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002596static PyObject *
2597task_step_impl(TaskObj *task, PyObject *exc)
2598{
2599 int res;
2600 int clear_exc = 0;
2601 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002602 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002603 PyObject *o;
2604
2605 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002606 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002607 "_step(): already done: %R %R",
2608 task,
2609 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002610 goto fail;
2611 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002612
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002613 if (task->task_must_cancel) {
2614 assert(exc != Py_None);
2615
2616 if (exc) {
2617 /* Check if exc is a CancelledError */
2618 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2619 if (res == -1) {
2620 /* An error occurred, abort */
2621 goto fail;
2622 }
2623 if (res == 0) {
2624 /* exc is not CancelledError; reset it to NULL */
2625 exc = NULL;
2626 }
2627 }
2628
2629 if (!exc) {
2630 /* exc was not a CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002631 exc = create_cancelled_error(task->task_cancel_msg);
2632
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002633 if (!exc) {
2634 goto fail;
2635 }
2636 clear_exc = 1;
2637 }
2638
2639 task->task_must_cancel = 0;
2640 }
2641
2642 Py_CLEAR(task->task_fut_waiter);
2643
Serhiy Storchakabca49392017-09-03 08:10:14 +03002644 coro = task->task_coro;
2645 if (coro == NULL) {
2646 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
Chris Jerdonekd2c349b2020-05-08 03:54:38 -07002647 if (clear_exc) {
2648 /* We created 'exc' during this call */
2649 Py_DECREF(exc);
2650 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002651 return NULL;
2652 }
2653
Vladimir Matveev2b053612020-09-18 18:38:38 -07002654 int gen_status = PYGEN_ERROR;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002655 if (exc == NULL) {
Vladimir Matveev037245c2020-10-09 17:15:15 -07002656 gen_status = PyIter_Send(coro, Py_None, &result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002657 }
2658 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002659 result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
Vladimir Matveev2b053612020-09-18 18:38:38 -07002660 gen_status = gen_status_from_result(&result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002661 if (clear_exc) {
2662 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002663 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002664 }
2665 }
2666
Vladimir Matveev2b053612020-09-18 18:38:38 -07002667 if (gen_status == PYGEN_RETURN || gen_status == PYGEN_ERROR) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002668 PyObject *et, *ev, *tb;
2669
Vladimir Matveev2b053612020-09-18 18:38:38 -07002670 if (result != NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002671 /* The error is StopIteration and that means that
2672 the underlying coroutine has resolved */
Yury Selivanovedad4d82019-09-25 03:32:08 -07002673
2674 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002675 if (task->task_must_cancel) {
2676 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002677 task->task_must_cancel = 0;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002678 res = future_cancel((FutureObj*)task, task->task_cancel_msg);
INADA Naoki991adca2017-05-11 21:18:38 +09002679 }
Yury Selivanovedad4d82019-09-25 03:32:08 -07002680 else {
Vladimir Matveev2b053612020-09-18 18:38:38 -07002681 res = future_set_result((FutureObj*)task, result);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002682 }
2683
Vladimir Matveev2b053612020-09-18 18:38:38 -07002684 Py_DECREF(result);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002685
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002686 if (res == NULL) {
2687 return NULL;
2688 }
2689 Py_DECREF(res);
2690 Py_RETURN_NONE;
2691 }
2692
2693 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2694 /* CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002695 PyErr_Fetch(&et, &ev, &tb);
2696
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002697 FutureObj *fut = (FutureObj*)task;
2698 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
2699 exc_state->exc_type = et;
2700 exc_state->exc_value = ev;
2701 exc_state->exc_traceback = tb;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002702
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002703 return future_cancel(fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002704 }
2705
2706 /* Some other exception; pop it and call Task.set_exception() */
2707 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002708
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002709 assert(et);
2710 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2711 PyErr_NormalizeException(&et, &ev, &tb);
2712 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002713 if (tb != NULL) {
2714 PyException_SetTraceback(ev, tb);
2715 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002716 o = future_set_exception((FutureObj*)task, ev);
2717 if (!o) {
2718 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002719 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002720 Py_XDECREF(tb);
2721 Py_XDECREF(ev);
2722 goto fail;
2723 }
2724 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002725 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002726
Yury Selivanov431b5402019-05-27 14:45:12 +02002727 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2728 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2729 {
2730 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002731 PyErr_Restore(et, ev, tb);
2732 goto fail;
2733 }
2734
Serhiy Storchakabca49392017-09-03 08:10:14 +03002735 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002736 Py_XDECREF(tb);
2737 Py_XDECREF(ev);
2738
2739 Py_RETURN_NONE;
2740 }
2741
2742 if (result == (PyObject*)task) {
2743 /* We have a task that wants to await on itself */
2744 goto self_await;
2745 }
2746
2747 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2748 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2749 PyObject *wrapper;
2750 PyObject *res;
2751 FutureObj *fut = (FutureObj*)result;
2752
2753 /* Check if `result` future is attached to a different loop */
2754 if (fut->fut_loop != task->task_loop) {
2755 goto different_loop;
2756 }
2757
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002758 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002759 goto yield_insteadof_yf;
2760 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002761
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002762 fut->fut_blocking = 0;
2763
2764 /* result.add_done_callback(task._wakeup) */
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07002765 wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002766 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002767 goto fail;
2768 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002769 res = future_add_done_callback(
2770 (FutureObj*)result, wrapper, task->task_context);
2771 Py_DECREF(wrapper);
2772 if (res == NULL) {
2773 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002774 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002775 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002776
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002777 /* task._fut_waiter = result */
2778 task->task_fut_waiter = result; /* no incref is necessary */
2779
2780 if (task->task_must_cancel) {
2781 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002782 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002783 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2784 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002785 if (r == NULL) {
2786 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002787 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002788 is_true = PyObject_IsTrue(r);
2789 Py_DECREF(r);
2790 if (is_true < 0) {
2791 return NULL;
2792 }
2793 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002794 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002795 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002796 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002797
2798 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002799 }
2800
2801 /* Check if `result` is None */
2802 if (result == Py_None) {
2803 /* Bare yield relinquishes control for one event loop iteration. */
2804 if (task_call_step_soon(task, NULL)) {
2805 goto fail;
2806 }
2807 return result;
2808 }
2809
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002810 /* Check if `result` is a Future-compatible object */
2811 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2812 goto fail;
2813 }
2814 if (o != NULL && o != Py_None) {
2815 /* `result` is a Future-compatible object */
2816 PyObject *wrapper;
2817 PyObject *res;
2818
2819 int blocking = PyObject_IsTrue(o);
2820 Py_DECREF(o);
2821 if (blocking < 0) {
2822 goto fail;
2823 }
2824
2825 /* Check if `result` future is attached to a different loop */
2826 PyObject *oloop = get_future_loop(result);
2827 if (oloop == NULL) {
2828 goto fail;
2829 }
2830 if (oloop != task->task_loop) {
2831 Py_DECREF(oloop);
2832 goto different_loop;
2833 }
2834 Py_DECREF(oloop);
2835
2836 if (!blocking) {
2837 goto yield_insteadof_yf;
2838 }
2839
2840 /* result._asyncio_future_blocking = False */
2841 if (_PyObject_SetAttrId(
2842 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2843 goto fail;
2844 }
2845
Vladimir Matveevc8ba47b2020-10-21 17:49:10 -07002846 wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002847 if (wrapper == NULL) {
2848 goto fail;
2849 }
2850
2851 /* result.add_done_callback(task._wakeup) */
2852 PyObject *add_cb = _PyObject_GetAttrId(
2853 result, &PyId_add_done_callback);
2854 if (add_cb == NULL) {
2855 Py_DECREF(wrapper);
2856 goto fail;
2857 }
2858 PyObject *stack[2];
2859 stack[0] = wrapper;
2860 stack[1] = (PyObject *)task->task_context;
Petr Viktorinffd97532020-02-11 17:46:57 +01002861 res = PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002862 Py_DECREF(add_cb);
2863 Py_DECREF(wrapper);
2864 if (res == NULL) {
2865 goto fail;
2866 }
2867 Py_DECREF(res);
2868
2869 /* task._fut_waiter = result */
2870 task->task_fut_waiter = result; /* no incref is necessary */
2871
2872 if (task->task_must_cancel) {
2873 PyObject *r;
2874 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002875 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2876 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002877 if (r == NULL) {
2878 return NULL;
2879 }
2880 is_true = PyObject_IsTrue(r);
2881 Py_DECREF(r);
2882 if (is_true < 0) {
2883 return NULL;
2884 }
2885 else if (is_true) {
2886 task->task_must_cancel = 0;
2887 }
2888 }
2889
2890 Py_RETURN_NONE;
2891 }
2892
2893 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002894 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002895 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2896 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002897 goto fail;
2898 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002899 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002900 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002901 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002902 task, PyExc_RuntimeError,
2903 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002904 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002905 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002906 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002907 }
2908
2909 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002910 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002911 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002912 Py_DECREF(result);
2913 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002914
2915self_await:
2916 o = task_set_error_soon(
2917 task, PyExc_RuntimeError,
2918 "Task cannot await on itself: %R", task);
2919 Py_DECREF(result);
2920 return o;
2921
2922yield_insteadof_yf:
2923 o = task_set_error_soon(
2924 task, PyExc_RuntimeError,
2925 "yield was used instead of yield from "
2926 "in task %R with %R",
2927 task, result);
2928 Py_DECREF(result);
2929 return o;
2930
2931different_loop:
2932 o = task_set_error_soon(
2933 task, PyExc_RuntimeError,
2934 "Task %R got Future %R attached to a different loop",
2935 task, result);
2936 Py_DECREF(result);
2937 return o;
2938
2939fail:
2940 Py_XDECREF(result);
2941 return NULL;
2942}
2943
2944static PyObject *
2945task_step(TaskObj *task, PyObject *exc)
2946{
2947 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002948
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002949 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002950 return NULL;
2951 }
2952
2953 res = task_step_impl(task, exc);
2954
2955 if (res == NULL) {
2956 PyObject *et, *ev, *tb;
2957 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002958 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002959 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002960 return NULL;
2961 }
2962 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002963 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002964 Py_DECREF(res);
2965 return NULL;
2966 }
2967 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002968 return res;
2969 }
2970 }
2971}
2972
2973static PyObject *
2974task_wakeup(TaskObj *task, PyObject *o)
2975{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002976 PyObject *et, *ev, *tb;
2977 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002978 assert(o);
2979
2980 if (Future_CheckExact(o) || Task_CheckExact(o)) {
2981 PyObject *fut_result = NULL;
2982 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002983
2984 switch(res) {
2985 case -1:
2986 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002987 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002988 case 0:
2989 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002990 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002991 default:
2992 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05002993 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002994 Py_DECREF(fut_result);
2995 return result;
2996 }
2997 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002998 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03002999 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
3000 if (fut_result != NULL) {
3001 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003002 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003003 }
3004 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003005 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003006
3007 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003008 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
3009 PyErr_NormalizeException(&et, &ev, &tb);
3010 }
3011
Yury Selivanov22feeb82018-01-24 11:31:01 -05003012 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003013
3014 Py_DECREF(et);
3015 Py_XDECREF(tb);
3016 Py_XDECREF(ev);
3017
3018 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003019}
3020
3021
Yury Selivanova70232f2017-12-13 14:49:42 -05003022/*********************** Functions **************************/
3023
3024
3025/*[clinic input]
3026_asyncio._get_running_loop
3027
3028Return the running event loop or None.
3029
3030This is a low-level function intended to be used by event loops.
3031This function is thread-specific.
3032
3033[clinic start generated code]*/
3034
3035static PyObject *
3036_asyncio__get_running_loop_impl(PyObject *module)
3037/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3038{
3039 PyObject *loop;
3040 if (get_running_loop(&loop)) {
3041 return NULL;
3042 }
3043 if (loop == NULL) {
3044 /* There's no currently running event loop */
3045 Py_RETURN_NONE;
3046 }
3047 return loop;
3048}
3049
3050/*[clinic input]
3051_asyncio._set_running_loop
3052 loop: 'O'
3053 /
3054
3055Set the running event loop.
3056
3057This is a low-level function intended to be used by event loops.
3058This function is thread-specific.
3059[clinic start generated code]*/
3060
3061static PyObject *
3062_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3063/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3064{
3065 if (set_running_loop(loop)) {
3066 return NULL;
3067 }
3068 Py_RETURN_NONE;
3069}
3070
3071/*[clinic input]
3072_asyncio.get_event_loop
3073
3074Return an asyncio event loop.
3075
3076When called from a coroutine or a callback (e.g. scheduled with
3077call_soon or similar API), this function will always return the
3078running event loop.
3079
3080If there is no running event loop set, the function will return
3081the result of `get_event_loop_policy().get_event_loop()` call.
3082[clinic start generated code]*/
3083
3084static PyObject *
3085_asyncio_get_event_loop_impl(PyObject *module)
3086/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3087{
Serhiy Storchaka172c0f22021-04-25 13:40:44 +03003088 return get_event_loop(1);
3089}
3090
3091/*[clinic input]
3092_asyncio._get_event_loop
3093 stacklevel: int = 3
3094[clinic start generated code]*/
3095
3096static PyObject *
3097_asyncio__get_event_loop_impl(PyObject *module, int stacklevel)
3098/*[clinic end generated code: output=9c1d6d3c802e67c9 input=d17aebbd686f711d]*/
3099{
3100 return get_event_loop(stacklevel-1);
Yury Selivanova70232f2017-12-13 14:49:42 -05003101}
3102
3103/*[clinic input]
3104_asyncio.get_running_loop
3105
3106Return the running event loop. Raise a RuntimeError if there is none.
3107
3108This function is thread-specific.
3109[clinic start generated code]*/
3110
3111static PyObject *
3112_asyncio_get_running_loop_impl(PyObject *module)
3113/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3114{
3115 PyObject *loop;
3116 if (get_running_loop(&loop)) {
3117 return NULL;
3118 }
3119 if (loop == NULL) {
3120 /* There's no currently running event loop */
3121 PyErr_SetString(
3122 PyExc_RuntimeError, "no running event loop");
3123 }
3124 return loop;
3125}
3126
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003127/*[clinic input]
3128_asyncio._register_task
3129
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003130 task: object
3131
3132Register a new task in asyncio as executed by loop.
3133
3134Returns None.
3135[clinic start generated code]*/
3136
3137static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003138_asyncio__register_task_impl(PyObject *module, PyObject *task)
3139/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003140{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003141 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003142 return NULL;
3143 }
3144 Py_RETURN_NONE;
3145}
3146
3147
3148/*[clinic input]
3149_asyncio._unregister_task
3150
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003151 task: object
3152
3153Unregister a task.
3154
3155Returns None.
3156[clinic start generated code]*/
3157
3158static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003159_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3160/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003161{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003162 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003163 return NULL;
3164 }
3165 Py_RETURN_NONE;
3166}
3167
3168
3169/*[clinic input]
3170_asyncio._enter_task
3171
3172 loop: object
3173 task: object
3174
3175Enter into task execution or resume suspended task.
3176
3177Task belongs to loop.
3178
3179Returns None.
3180[clinic start generated code]*/
3181
3182static PyObject *
3183_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3184/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3185{
3186 if (enter_task(loop, task) < 0) {
3187 return NULL;
3188 }
3189 Py_RETURN_NONE;
3190}
3191
3192
3193/*[clinic input]
3194_asyncio._leave_task
3195
3196 loop: object
3197 task: object
3198
3199Leave task execution or suspend a task.
3200
3201Task belongs to loop.
3202
3203Returns None.
3204[clinic start generated code]*/
3205
3206static PyObject *
3207_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3208/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3209{
3210 if (leave_task(loop, task) < 0) {
3211 return NULL;
3212 }
3213 Py_RETURN_NONE;
3214}
3215
Yury Selivanova70232f2017-12-13 14:49:42 -05003216
Yury Selivanov9d411c12018-01-23 15:10:03 -05003217/*********************** PyRunningLoopHolder ********************/
3218
3219
3220static PyRunningLoopHolder *
3221new_running_loop_holder(PyObject *loop)
3222{
3223 PyRunningLoopHolder *rl = PyObject_New(
3224 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3225 if (rl == NULL) {
3226 return NULL;
3227 }
3228
3229#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3230 rl->rl_pid = getpid();
3231#endif
3232
3233 Py_INCREF(loop);
3234 rl->rl_loop = loop;
3235
3236 return rl;
3237}
3238
3239
3240static void
3241PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3242{
3243 Py_CLEAR(rl->rl_loop);
3244 PyObject_Free(rl);
3245}
3246
3247
3248static PyTypeObject PyRunningLoopHolder_Type = {
3249 PyVarObject_HEAD_INIT(NULL, 0)
3250 "_RunningLoopHolder",
3251 sizeof(PyRunningLoopHolder),
3252 .tp_getattro = PyObject_GenericGetAttr,
3253 .tp_flags = Py_TPFLAGS_DEFAULT,
3254 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3255};
3256
3257
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003258/*********************** Module **************************/
3259
3260
3261static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003262module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003263{
3264 PyObject *next;
3265 PyObject *current;
3266
3267 next = (PyObject*) fi_freelist;
3268 while (next != NULL) {
3269 assert(fi_freelist_len > 0);
3270 fi_freelist_len--;
3271
3272 current = next;
3273 next = (PyObject*) ((futureiterobject*) current)->future;
3274 PyObject_GC_Del(current);
3275 }
3276 assert(fi_freelist_len == 0);
3277 fi_freelist = NULL;
3278}
3279
3280
3281static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003282module_free(void *m)
3283{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003284 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003285 Py_CLEAR(traceback_extract_stack);
3286 Py_CLEAR(asyncio_future_repr_info_func);
3287 Py_CLEAR(asyncio_get_event_loop_policy);
3288 Py_CLEAR(asyncio_iscoroutine_func);
3289 Py_CLEAR(asyncio_task_get_stack_func);
3290 Py_CLEAR(asyncio_task_print_stack_func);
3291 Py_CLEAR(asyncio_task_repr_info_func);
3292 Py_CLEAR(asyncio_InvalidStateError);
3293 Py_CLEAR(asyncio_CancelledError);
3294
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003295 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003296 Py_CLEAR(current_tasks);
3297 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003298
Yury Selivanovf23746a2018-01-22 19:11:18 -05003299 Py_CLEAR(context_kwname);
3300
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003301 module_free_freelists();
Jeffrey Quesnellea75e7302020-04-16 22:09:45 -04003302
3303 module_initialized = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003304}
3305
3306static int
3307module_init(void)
3308{
3309 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003310
3311 asyncio_mod = PyImport_ImportModule("asyncio");
3312 if (asyncio_mod == NULL) {
3313 goto fail;
3314 }
Ben Harper321def82019-10-07 12:19:58 -04003315 if (module_initialized != 0) {
3316 return 0;
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02003317 }
Ben Harper321def82019-10-07 12:19:58 -04003318 else {
3319 module_initialized = 1;
3320 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003321
3322 current_tasks = PyDict_New();
3323 if (current_tasks == NULL) {
3324 goto fail;
3325 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003326
Yury Selivanova9d7e552017-12-19 07:18:45 -05003327 iscoroutine_typecache = PySet_New(NULL);
3328 if (iscoroutine_typecache == NULL) {
3329 goto fail;
3330 }
3331
Yury Selivanovf23746a2018-01-22 19:11:18 -05003332
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003333 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003334 if (context_kwname == NULL) {
3335 goto fail;
3336 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003337
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003338#define WITH_MOD(NAME) \
3339 Py_CLEAR(module); \
3340 module = PyImport_ImportModule(NAME); \
3341 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003342 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003343 }
3344
3345#define GET_MOD_ATTR(VAR, NAME) \
3346 VAR = PyObject_GetAttrString(module, NAME); \
3347 if (VAR == NULL) { \
3348 goto fail; \
3349 }
3350
3351 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003352 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003353
3354 WITH_MOD("asyncio.base_futures")
3355 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003356
3357 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003358 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3359 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3360
3361 WITH_MOD("asyncio.base_tasks")
3362 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3363 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3364 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3365
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003366 WITH_MOD("asyncio.coroutines")
3367 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3368
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003369 WITH_MOD("traceback")
3370 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3371
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003372 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003373 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003374 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003375 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003376 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003377 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003378 goto fail;
3379 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003380
Serhiy Storchakabca49392017-09-03 08:10:14 +03003381 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003382 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003383
INADA Naokic411a7d2016-10-18 11:48:14 +09003384fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003385 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003386 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003387 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003388
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003389#undef WITH_MOD
3390#undef GET_MOD_ATTR
3391}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003392
INADA Naokic411a7d2016-10-18 11:48:14 +09003393PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003394
Yury Selivanova70232f2017-12-13 14:49:42 -05003395static PyMethodDef asyncio_methods[] = {
3396 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
Serhiy Storchaka172c0f22021-04-25 13:40:44 +03003397 _ASYNCIO__GET_EVENT_LOOP_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003398 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3399 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3400 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003401 _ASYNCIO__REGISTER_TASK_METHODDEF
3402 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3403 _ASYNCIO__ENTER_TASK_METHODDEF
3404 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003405 {NULL, NULL}
3406};
3407
INADA Naoki9f2ce252016-10-15 15:39:19 +09003408static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003409 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003410 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003411 module_doc, /* m_doc */
3412 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003413 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003414 NULL, /* m_slots */
3415 NULL, /* m_traverse */
3416 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003417 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003418};
3419
3420
3421PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003422PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003423{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003424 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003425 return NULL;
3426 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003427 if (PyType_Ready(&FutureIterType) < 0) {
3428 return NULL;
3429 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003430 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003431 return NULL;
3432 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003433 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3434 return NULL;
3435 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003436
INADA Naoki9f2ce252016-10-15 15:39:19 +09003437 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003438 if (m == NULL) {
3439 return NULL;
3440 }
3441
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003442 /* FutureType and TaskType are made ready by PyModule_AddType() calls below. */
3443 if (PyModule_AddType(m, &FutureType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003444 Py_DECREF(m);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003445 return NULL;
3446 }
3447
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003448 if (PyModule_AddType(m, &TaskType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003449 Py_DECREF(m);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003450 return NULL;
3451 }
3452
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003453 Py_INCREF(all_tasks);
3454 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3455 Py_DECREF(all_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003456 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003457 return NULL;
3458 }
3459
3460 Py_INCREF(current_tasks);
3461 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3462 Py_DECREF(current_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003463 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003464 return NULL;
3465 }
3466
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003467 return m;
3468}