blob: 22eea3b5bab21025757c648e8c600cf0e1a0bf2f [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(send);
20_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090021
22
INADA Naoki9f2ce252016-10-15 15:39:19 +090023/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020024static PyObject *asyncio_mod;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020025static PyObject *traceback_extract_stack;
26static PyObject *asyncio_get_event_loop_policy;
27static PyObject *asyncio_future_repr_info_func;
28static PyObject *asyncio_iscoroutine_func;
29static PyObject *asyncio_task_get_stack_func;
30static PyObject *asyncio_task_print_stack_func;
31static PyObject *asyncio_task_repr_info_func;
32static PyObject *asyncio_InvalidStateError;
33static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050034static PyObject *context_kwname;
Ben Harper321def82019-10-07 12:19:58 -040035static int module_initialized;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020036
Yury Selivanov9d411c12018-01-23 15:10:03 -050037static PyObject *cached_running_holder;
38static volatile uint64_t cached_running_holder_tsid;
39
Alex Grönholmcca4eec2018-08-09 00:06:47 +030040/* Counter for autogenerated Task names */
41static uint64_t task_name_counter = 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020042
Yury Selivanovca9b36c2017-12-23 15:04:15 -050043/* WeakSet containing all alive tasks. */
44static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020045
46/* Dictionary containing tasks that are currently active in
47 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050048static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090049
Yury Selivanova9d7e552017-12-19 07:18:45 -050050/* An isinstance type cache for the 'is_coroutine()' function. */
51static PyObject *iscoroutine_typecache;
52
INADA Naoki9e4e38e2016-10-09 14:44:47 +090053
INADA Naoki9e4e38e2016-10-09 14:44:47 +090054typedef enum {
55 STATE_PENDING,
56 STATE_CANCELLED,
57 STATE_FINISHED
58} fut_state;
59
Yury Selivanova0c1ba62016-10-28 12:52:37 -040060#define FutureObj_HEAD(prefix) \
61 PyObject_HEAD \
62 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050063 PyObject *prefix##_callback0; \
Yury Selivanov994269c2018-09-27 14:55:55 -040064 PyObject *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040065 PyObject *prefix##_callbacks; \
66 PyObject *prefix##_exception; \
67 PyObject *prefix##_result; \
68 PyObject *prefix##_source_tb; \
Chris Jerdonek1ce58412020-05-15 16:55:50 -070069 PyObject *prefix##_cancel_msg; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040070 fut_state prefix##_state; \
71 int prefix##_log_tb; \
72 int prefix##_blocking; \
73 PyObject *dict; \
Chris Jerdonekda742ba2020-05-17 22:47:31 -070074 PyObject *prefix##_weakreflist; \
75 _PyErr_StackItem prefix##_cancelled_exc_state;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040076
77typedef struct {
78 FutureObj_HEAD(fut)
79} FutureObj;
80
81typedef struct {
82 FutureObj_HEAD(task)
83 PyObject *task_fut_waiter;
84 PyObject *task_coro;
Alex Grönholmcca4eec2018-08-09 00:06:47 +030085 PyObject *task_name;
Yury Selivanov994269c2018-09-27 14:55:55 -040086 PyObject *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040087 int task_must_cancel;
88 int task_log_destroy_pending;
89} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090090
91typedef struct {
92 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040093 TaskObj *sw_task;
94 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030095} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090096
Yury Selivanova0c1ba62016-10-28 12:52:37 -040097typedef struct {
98 PyObject_HEAD
99 TaskObj *ww_task;
100} TaskWakeupMethWrapper;
101
Yury Selivanov9d411c12018-01-23 15:10:03 -0500102typedef struct {
103 PyObject_HEAD
104 PyObject *rl_loop;
105#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
106 pid_t rl_pid;
107#endif
108} PyRunningLoopHolder;
109
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400110
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500111static PyTypeObject FutureType;
112static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500113static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500114
115
Dong-hee Na1b55b652020-02-17 19:09:15 +0900116#define Future_CheckExact(obj) Py_IS_TYPE(obj, &FutureType)
117#define Task_CheckExact(obj) Py_IS_TYPE(obj, &TaskType)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500118
119#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
120#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
121
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400122#include "clinic/_asynciomodule.c.h"
123
124
125/*[clinic input]
126class _asyncio.Future "FutureObj *" "&Future_Type"
127[clinic start generated code]*/
128/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
129
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500130
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400131/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500132static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900133
Yury Selivanov9d411c12018-01-23 15:10:03 -0500134static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
135
Yury Selivanova70232f2017-12-13 14:49:42 -0500136
137static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500138_is_coroutine(PyObject *coro)
139{
140 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
141 to check if it's another coroutine flavour.
142
143 Do this check after 'future_init()'; in case we need to raise
144 an error, __del__ needs a properly initialized object.
145 */
Petr Viktorinffd97532020-02-11 17:46:57 +0100146 PyObject *res = PyObject_CallOneArg(asyncio_iscoroutine_func, coro);
Yury Selivanova9d7e552017-12-19 07:18:45 -0500147 if (res == NULL) {
148 return -1;
149 }
150
151 int is_res_true = PyObject_IsTrue(res);
152 Py_DECREF(res);
153 if (is_res_true <= 0) {
154 return is_res_true;
155 }
156
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200157 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500158 /* Just in case we don't want to cache more than 100
159 positive types. That shouldn't ever happen, unless
160 someone stressing the system on purpose.
161 */
162 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
163 return -1;
164 }
165 }
166
167 return 1;
168}
169
170
171static inline int
172is_coroutine(PyObject *coro)
173{
174 if (PyCoro_CheckExact(coro)) {
175 return 1;
176 }
177
178 /* Check if `type(coro)` is in the cache.
179 Caching makes is_coroutine() function almost as fast as
180 PyCoro_CheckExact() for non-native coroutine-like objects
181 (like coroutines compiled with Cython).
182
183 asyncio.iscoroutine() has its own type caching mechanism.
184 This cache allows us to avoid the cost of even calling
185 a pure-Python function in 99.9% cases.
186 */
187 int has_it = PySet_Contains(
188 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
189 if (has_it == 0) {
190 /* type(coro) is not in iscoroutine_typecache */
191 return _is_coroutine(coro);
192 }
193
Leo Ariasc3d95082018-02-03 18:36:10 -0600194 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500195 type(coro) is in iscoroutine_typecache
196 */
197 return has_it;
198}
199
200
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500201static PyObject *
202get_future_loop(PyObject *fut)
203{
204 /* Implementation of `asyncio.futures._get_loop` */
205
206 _Py_IDENTIFIER(get_loop);
207 _Py_IDENTIFIER(_loop);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300208 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500209
210 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
211 PyObject *loop = ((FutureObj *)fut)->fut_loop;
212 Py_INCREF(loop);
213 return loop;
214 }
215
Serhiy Storchaka66553542018-05-20 16:30:31 +0300216 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
217 return NULL;
218 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500219 if (getloop != NULL) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200220 PyObject *res = PyObject_CallNoArgs(getloop);
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500221 Py_DECREF(getloop);
222 return res;
223 }
224
225 return _PyObject_GetAttrId(fut, &PyId__loop);
226}
227
228
Yury Selivanova9d7e552017-12-19 07:18:45 -0500229static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500230get_running_loop(PyObject **loop)
231{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500232 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500233
Yury Selivanov9d411c12018-01-23 15:10:03 -0500234 PyThreadState *ts = PyThreadState_Get();
Victor Stinner5c3cda02020-03-25 21:23:53 +0100235 uint64_t ts_id = PyThreadState_GetID(ts);
236 if (ts_id == cached_running_holder_tsid && cached_running_holder != NULL) {
Yury Selivanov9d411c12018-01-23 15:10:03 -0500237 // Fast path, check the cache.
238 rl = cached_running_holder; // borrowed
239 }
240 else {
Victor Stinner0e427c62020-03-25 21:22:55 +0100241 PyObject *ts_dict = _PyThreadState_GetDict(ts); // borrowed
242 if (ts_dict == NULL) {
Yury Selivanov9d411c12018-01-23 15:10:03 -0500243 goto not_found;
244 }
245
246 rl = _PyDict_GetItemIdWithError(
Victor Stinner0e427c62020-03-25 21:22:55 +0100247 ts_dict, &PyId___asyncio_running_event_loop__); // borrowed
Yury Selivanov9d411c12018-01-23 15:10:03 -0500248 if (rl == NULL) {
249 if (PyErr_Occurred()) {
250 goto error;
251 }
252 else {
253 goto not_found;
254 }
255 }
256
257 cached_running_holder = rl; // borrowed
Victor Stinner5c3cda02020-03-25 21:23:53 +0100258 cached_running_holder_tsid = ts_id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500259 }
260
Dong-hee Na1b55b652020-02-17 19:09:15 +0900261 assert(Py_IS_TYPE(rl, &PyRunningLoopHolder_Type));
Yury Selivanov9d411c12018-01-23 15:10:03 -0500262 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500263
264 if (running_loop == Py_None) {
265 goto not_found;
266 }
267
Yury Selivanov9d411c12018-01-23 15:10:03 -0500268#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
269 /* On Windows there is no getpid, but there is also no os.fork(),
270 so there is no need for this check.
271 */
272 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
273 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500274 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500275#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500276
Yury Selivanov9d411c12018-01-23 15:10:03 -0500277 Py_INCREF(running_loop);
278 *loop = running_loop;
279 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500280
281not_found:
282 *loop = NULL;
283 return 0;
284
Yury Selivanova70232f2017-12-13 14:49:42 -0500285error:
286 *loop = NULL;
287 return -1;
288}
289
290
291static int
292set_running_loop(PyObject *loop)
293{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500294 cached_running_holder = NULL;
295 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500296
Yury Selivanov9d411c12018-01-23 15:10:03 -0500297 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500298 if (ts_dict == NULL) {
299 PyErr_SetString(
300 PyExc_RuntimeError, "thread-local storage is not available");
301 return -1;
302 }
303
Yury Selivanov9d411c12018-01-23 15:10:03 -0500304 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
305 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500306 return -1;
307 }
308
Yury Selivanova70232f2017-12-13 14:49:42 -0500309 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500310 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
311 {
312 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500313 return -1;
314 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500315 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500316
317 return 0;
318}
319
320
321static PyObject *
322get_event_loop(void)
323{
324 PyObject *loop;
325 PyObject *policy;
326
327 if (get_running_loop(&loop)) {
328 return NULL;
329 }
330 if (loop != NULL) {
331 return loop;
332 }
333
Victor Stinner2ff58a22019-06-17 14:27:23 +0200334 policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy);
Yury Selivanova70232f2017-12-13 14:49:42 -0500335 if (policy == NULL) {
336 return NULL;
337 }
338
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200339 loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
Yury Selivanova70232f2017-12-13 14:49:42 -0500340 Py_DECREF(policy);
341 return loop;
342}
343
344
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900345static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400346call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500347{
348 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500349 PyObject *stack[3];
350 Py_ssize_t nargs;
351
352 if (ctx == NULL) {
353 handle = _PyObject_CallMethodIdObjArgs(
354 loop, &PyId_call_soon, func, arg, NULL);
355 }
356 else {
357 /* Use FASTCALL to pass a keyword-only argument to call_soon */
358
359 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
360 if (callable == NULL) {
361 return -1;
362 }
363
364 /* All refs in 'stack' are borrowed. */
365 nargs = 1;
366 stack[0] = func;
367 if (arg != NULL) {
368 stack[1] = arg;
369 nargs++;
370 }
371 stack[nargs] = (PyObject *)ctx;
372
Petr Viktorinffd97532020-02-11 17:46:57 +0100373 handle = PyObject_Vectorcall(callable, stack, nargs, context_kwname);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500374 Py_DECREF(callable);
375 }
376
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500377 if (handle == NULL) {
378 return -1;
379 }
380 Py_DECREF(handle);
381 return 0;
382}
383
384
385static inline int
386future_is_alive(FutureObj *fut)
387{
388 return fut->fut_loop != NULL;
389}
390
391
392static inline int
393future_ensure_alive(FutureObj *fut)
394{
395 if (!future_is_alive(fut)) {
396 PyErr_SetString(PyExc_RuntimeError,
397 "Future object is not initialized.");
398 return -1;
399 }
400 return 0;
401}
402
403
404#define ENSURE_FUTURE_ALIVE(fut) \
405 do { \
406 assert(Future_Check(fut) || Task_Check(fut)); \
407 if (future_ensure_alive((FutureObj*)fut)) { \
408 return NULL; \
409 } \
410 } while(0);
411
412
413static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400414future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900415{
416 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500417 Py_ssize_t i;
418
419 if (fut->fut_callback0 != NULL) {
420 /* There's a 1st callback */
421
422 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500423 fut->fut_loop, fut->fut_callback0,
424 (PyObject *)fut, fut->fut_context0);
425
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500426 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500427 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500428 if (ret) {
429 /* If an error occurs in pure-Python implementation,
430 all callbacks are cleared. */
431 Py_CLEAR(fut->fut_callbacks);
432 return ret;
433 }
434
435 /* we called the first callback, now try calling
436 callbacks from the 'fut_callbacks' list. */
437 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900438
439 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500440 /* No more callbacks, return. */
441 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900442 }
443
444 len = PyList_GET_SIZE(fut->fut_callbacks);
445 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500446 /* The list of callbacks was empty; clear it and return. */
447 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900448 return 0;
449 }
450
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900451 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500452 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
453 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
454 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900455
Yury Selivanov994269c2018-09-27 14:55:55 -0400456 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500457 /* If an error occurs in pure-Python implementation,
458 all callbacks are cleared. */
459 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900460 return -1;
461 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900462 }
463
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500464 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900465 return 0;
466}
467
Oren Milmand019bc82018-02-13 12:28:33 +0200468
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900469static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400470future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900471{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300472 PyObject *res;
473 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900474 _Py_IDENTIFIER(get_debug);
475
Oren Milmand019bc82018-02-13 12:28:33 +0200476 // Same to FutureObj_clear() but not clearing fut->dict
477 Py_CLEAR(fut->fut_loop);
478 Py_CLEAR(fut->fut_callback0);
479 Py_CLEAR(fut->fut_context0);
480 Py_CLEAR(fut->fut_callbacks);
481 Py_CLEAR(fut->fut_result);
482 Py_CLEAR(fut->fut_exception);
483 Py_CLEAR(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700484 Py_CLEAR(fut->fut_cancel_msg);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700485 _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
Oren Milmand019bc82018-02-13 12:28:33 +0200486
487 fut->fut_state = STATE_PENDING;
488 fut->fut_log_tb = 0;
489 fut->fut_blocking = 0;
490
Serhiy Storchakabca49392017-09-03 08:10:14 +0300491 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500492 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900493 if (loop == NULL) {
494 return -1;
495 }
496 }
497 else {
498 Py_INCREF(loop);
499 }
Oren Milmand019bc82018-02-13 12:28:33 +0200500 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900501
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200502 res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900503 if (res == NULL) {
504 return -1;
505 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300506 is_true = PyObject_IsTrue(res);
507 Py_DECREF(res);
508 if (is_true < 0) {
509 return -1;
510 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400511 if (is_true && !_Py_IsFinalizing()) {
512 /* Only try to capture the traceback if the interpreter is not being
513 finalized. The original motivation to add a `_Py_IsFinalizing()`
514 call was to prevent SIGSEGV when a Future is created in a __del__
515 method, which is called during the interpreter shutdown and the
516 traceback module is already unloaded.
517 */
Victor Stinner2ff58a22019-06-17 14:27:23 +0200518 fut->fut_source_tb = PyObject_CallNoArgs(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900519 if (fut->fut_source_tb == NULL) {
520 return -1;
521 }
522 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900523
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900524 return 0;
525}
526
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900527static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400528future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900529{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500530 if (future_ensure_alive(fut)) {
531 return NULL;
532 }
533
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900534 if (fut->fut_state != STATE_PENDING) {
535 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
536 return NULL;
537 }
538
Serhiy Storchakabca49392017-09-03 08:10:14 +0300539 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900540 Py_INCREF(res);
541 fut->fut_result = res;
542 fut->fut_state = STATE_FINISHED;
543
Yury Selivanov22feeb82018-01-24 11:31:01 -0500544 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900545 return NULL;
546 }
547 Py_RETURN_NONE;
548}
549
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900550static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400551future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900552{
553 PyObject *exc_val = NULL;
554
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900555 if (fut->fut_state != STATE_PENDING) {
556 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
557 return NULL;
558 }
559
560 if (PyExceptionClass_Check(exc)) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200561 exc_val = PyObject_CallNoArgs(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900562 if (exc_val == NULL) {
563 return NULL;
564 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300565 if (fut->fut_state != STATE_PENDING) {
566 Py_DECREF(exc_val);
567 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
568 return NULL;
569 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900570 }
571 else {
572 exc_val = exc;
573 Py_INCREF(exc_val);
574 }
575 if (!PyExceptionInstance_Check(exc_val)) {
576 Py_DECREF(exc_val);
577 PyErr_SetString(PyExc_TypeError, "invalid exception object");
578 return NULL;
579 }
Andy Lesterdffe4c02020-03-04 07:15:20 -0600580 if (Py_IS_TYPE(exc_val, (PyTypeObject *)PyExc_StopIteration)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900581 Py_DECREF(exc_val);
582 PyErr_SetString(PyExc_TypeError,
583 "StopIteration interacts badly with generators "
584 "and cannot be raised into a Future");
585 return NULL;
586 }
587
Serhiy Storchakabca49392017-09-03 08:10:14 +0300588 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900589 fut->fut_exception = exc_val;
590 fut->fut_state = STATE_FINISHED;
591
Yury Selivanov22feeb82018-01-24 11:31:01 -0500592 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900593 return NULL;
594 }
595
596 fut->fut_log_tb = 1;
597 Py_RETURN_NONE;
598}
599
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700600static PyObject *
601create_cancelled_error(PyObject *msg)
602{
603 PyObject *exc;
604 if (msg == NULL || msg == Py_None) {
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700605 exc = PyObject_CallNoArgs(asyncio_CancelledError);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700606 } else {
607 exc = PyObject_CallOneArg(asyncio_CancelledError, msg);
608 }
609 return exc;
610}
611
612static void
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700613future_set_cancelled_error(FutureObj *fut)
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700614{
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700615 PyObject *exc = create_cancelled_error(fut->fut_cancel_msg);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700616 PyErr_SetObject(asyncio_CancelledError, exc);
617 Py_DECREF(exc);
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700618
619 _PyErr_ChainStackItem(&fut->fut_cancelled_exc_state);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700620}
621
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400622static int
623future_get_result(FutureObj *fut, PyObject **result)
624{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400625 if (fut->fut_state == STATE_CANCELLED) {
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700626 future_set_cancelled_error(fut);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300627 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400628 }
629
630 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300631 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
632 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400633 }
634
635 fut->fut_log_tb = 0;
636 if (fut->fut_exception != NULL) {
637 Py_INCREF(fut->fut_exception);
638 *result = fut->fut_exception;
639 return 1;
640 }
641
642 Py_INCREF(fut->fut_result);
643 *result = fut->fut_result;
644 return 0;
645}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900646
647static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400648future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900649{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500650 if (!future_is_alive(fut)) {
651 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
652 return NULL;
653 }
654
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900655 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500656 /* The future is done/cancelled, so schedule the callback
657 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500658 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900659 return NULL;
660 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900661 }
662 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500663 /* The future is pending, add a callback.
664
665 Callbacks in the future object are stored as follows:
666
667 callback0 -- a pointer to the first callback
668 callbacks -- a list of 2nd, 3rd, ... callbacks
669
670 Invariants:
671
672 * callbacks != NULL:
673 There are some callbacks in in the list. Just
674 add the new callback to it.
675
676 * callbacks == NULL and callback0 == NULL:
677 This is the first callback. Set it to callback0.
678
679 * callbacks == NULL and callback0 != NULL:
680 This is a second callback. Initialize callbacks
681 with a new list and add the new callback to it.
682 */
683
Yury Selivanovf23746a2018-01-22 19:11:18 -0500684 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500685 Py_INCREF(arg);
686 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500687 Py_INCREF(ctx);
688 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500689 }
690 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500691 PyObject *tup = PyTuple_New(2);
692 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500693 return NULL;
694 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500695 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500696 PyTuple_SET_ITEM(tup, 0, arg);
697 Py_INCREF(ctx);
698 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
699
700 if (fut->fut_callbacks != NULL) {
701 int err = PyList_Append(fut->fut_callbacks, tup);
702 if (err) {
703 Py_DECREF(tup);
704 return NULL;
705 }
706 Py_DECREF(tup);
707 }
708 else {
709 fut->fut_callbacks = PyList_New(1);
710 if (fut->fut_callbacks == NULL) {
711 return NULL;
712 }
713
714 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
715 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900716 }
717 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500718
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900719 Py_RETURN_NONE;
720}
721
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400722static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700723future_cancel(FutureObj *fut, PyObject *msg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400724{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000725 fut->fut_log_tb = 0;
726
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400727 if (fut->fut_state != STATE_PENDING) {
728 Py_RETURN_FALSE;
729 }
730 fut->fut_state = STATE_CANCELLED;
731
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700732 Py_XINCREF(msg);
733 Py_XSETREF(fut->fut_cancel_msg, msg);
734
Yury Selivanov22feeb82018-01-24 11:31:01 -0500735 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400736 return NULL;
737 }
738
739 Py_RETURN_TRUE;
740}
741
742/*[clinic input]
743_asyncio.Future.__init__
744
745 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300746 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400747
748This class is *almost* compatible with concurrent.futures.Future.
749
750 Differences:
751
752 - result() and exception() do not take a timeout argument and
753 raise an exception when the future isn't done yet.
754
755 - Callbacks registered with add_done_callback() are always called
756 via the event loop's call_soon_threadsafe().
757
758 - This class is not compatible with the wait() and as_completed()
759 methods in the concurrent.futures package.
760[clinic start generated code]*/
761
762static int
763_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300764/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400765
766{
767 return future_init(self, loop);
768}
769
770static int
771FutureObj_clear(FutureObj *fut)
772{
773 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500774 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500775 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400776 Py_CLEAR(fut->fut_callbacks);
777 Py_CLEAR(fut->fut_result);
778 Py_CLEAR(fut->fut_exception);
779 Py_CLEAR(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700780 Py_CLEAR(fut->fut_cancel_msg);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700781 _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400782 Py_CLEAR(fut->dict);
783 return 0;
784}
785
786static int
787FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
788{
789 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500790 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500791 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400792 Py_VISIT(fut->fut_callbacks);
793 Py_VISIT(fut->fut_result);
794 Py_VISIT(fut->fut_exception);
795 Py_VISIT(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700796 Py_VISIT(fut->fut_cancel_msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400797 Py_VISIT(fut->dict);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700798
799 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
800 Py_VISIT(exc_state->exc_type);
801 Py_VISIT(exc_state->exc_value);
802 Py_VISIT(exc_state->exc_traceback);
803
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400804 return 0;
805}
806
807/*[clinic input]
808_asyncio.Future.result
809
810Return the result this future represents.
811
812If the future has been cancelled, raises CancelledError. If the
813future's result isn't yet available, raises InvalidStateError. If
814the future is done and has an exception set, this exception is raised.
815[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900816
817static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400818_asyncio_Future_result_impl(FutureObj *self)
819/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
820{
821 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500822
823 if (!future_is_alive(self)) {
824 PyErr_SetString(asyncio_InvalidStateError,
825 "Future object is not initialized.");
826 return NULL;
827 }
828
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400829 int res = future_get_result(self, &result);
830
831 if (res == -1) {
832 return NULL;
833 }
834
835 if (res == 0) {
836 return result;
837 }
838
839 assert(res == 1);
840
841 PyErr_SetObject(PyExceptionInstance_Class(result), result);
842 Py_DECREF(result);
843 return NULL;
844}
845
846/*[clinic input]
847_asyncio.Future.exception
848
849Return the exception that was set on this future.
850
851The exception (or None if no exception was set) is returned only if
852the future is done. If the future has been cancelled, raises
853CancelledError. If the future isn't done yet, raises
854InvalidStateError.
855[clinic start generated code]*/
856
857static PyObject *
858_asyncio_Future_exception_impl(FutureObj *self)
859/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
860{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500861 if (!future_is_alive(self)) {
862 PyErr_SetString(asyncio_InvalidStateError,
863 "Future object is not initialized.");
864 return NULL;
865 }
866
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400867 if (self->fut_state == STATE_CANCELLED) {
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700868 future_set_cancelled_error(self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400869 return NULL;
870 }
871
872 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300873 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400874 return NULL;
875 }
876
877 if (self->fut_exception != NULL) {
878 self->fut_log_tb = 0;
879 Py_INCREF(self->fut_exception);
880 return self->fut_exception;
881 }
882
883 Py_RETURN_NONE;
884}
885
886/*[clinic input]
887_asyncio.Future.set_result
888
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500889 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400890 /
891
892Mark the future done and set its result.
893
894If the future is already done when this method is called, raises
895InvalidStateError.
896[clinic start generated code]*/
897
898static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500899_asyncio_Future_set_result(FutureObj *self, PyObject *result)
900/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400901{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500902 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500903 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400904}
905
906/*[clinic input]
907_asyncio.Future.set_exception
908
Serhiy Storchakabca49392017-09-03 08:10:14 +0300909 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400910 /
911
912Mark the future done and set an exception.
913
914If the future is already done when this method is called, raises
915InvalidStateError.
916[clinic start generated code]*/
917
918static PyObject *
919_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300920/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400921{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500922 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400923 return future_set_exception(self, exception);
924}
925
926/*[clinic input]
927_asyncio.Future.add_done_callback
928
Serhiy Storchakabca49392017-09-03 08:10:14 +0300929 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400930 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500931 *
932 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400933
934Add a callback to be run when the future becomes done.
935
936The callback is called with a single argument - the future object. If
937the future is already done when this is called, the callback is
938scheduled with call_soon.
939[clinic start generated code]*/
940
941static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500942_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
943 PyObject *context)
944/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400945{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500946 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400947 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500948 if (context == NULL) {
949 return NULL;
950 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400951 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500952 Py_DECREF(context);
953 return res;
954 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400955 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400956}
957
958/*[clinic input]
959_asyncio.Future.remove_done_callback
960
Serhiy Storchakabca49392017-09-03 08:10:14 +0300961 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400962 /
963
964Remove all instances of a callback from the "call when done" list.
965
966Returns the number of callbacks removed.
967[clinic start generated code]*/
968
969static PyObject *
970_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300971/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900972{
973 PyObject *newlist;
974 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500975 Py_ssize_t cleared_callback0 = 0;
976
977 ENSURE_FUTURE_ALIVE(self)
978
979 if (self->fut_callback0 != NULL) {
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300980 int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500981 if (cmp == -1) {
982 return NULL;
983 }
984 if (cmp == 1) {
985 /* callback0 == fn */
986 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500987 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500988 cleared_callback0 = 1;
989 }
990 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900991
Serhiy Storchakabca49392017-09-03 08:10:14 +0300992 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500993 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300994 }
995
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400996 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900997 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500998 Py_CLEAR(self->fut_callbacks);
999 return PyLong_FromSsize_t(cleared_callback0);
1000 }
1001
1002 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -05001003 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001004 int cmp = PyObject_RichCompareBool(
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001005 PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001006 if (cmp == -1) {
1007 return NULL;
1008 }
1009 if (cmp == 1) {
1010 /* callbacks[0] == fn */
1011 Py_CLEAR(self->fut_callbacks);
1012 return PyLong_FromSsize_t(1 + cleared_callback0);
1013 }
1014 /* callbacks[0] != fn and len(callbacks) == 1 */
1015 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001016 }
1017
1018 newlist = PyList_New(len);
1019 if (newlist == NULL) {
1020 return NULL;
1021 }
1022
Yury Selivanov84af9032017-03-02 23:46:56 -05001023 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001024 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001025 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001026 Py_INCREF(item);
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001027 ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001028 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001029 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001030 PyList_SET_ITEM(newlist, j, item);
1031 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001032 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -04001033 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001034 ret = PyList_Append(newlist, item);
1035 }
1036 Py_DECREF(item);
1037 if (ret < 0) {
1038 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001039 }
1040 }
1041
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001042 if (j == 0) {
1043 Py_CLEAR(self->fut_callbacks);
1044 Py_DECREF(newlist);
1045 return PyLong_FromSsize_t(len + cleared_callback0);
1046 }
1047
Serhiy Storchakabca49392017-09-03 08:10:14 +03001048 if (j < len) {
Victor Stinner60ac6ed2020-02-07 23:18:08 +01001049 Py_SET_SIZE(newlist, j);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001050 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001051 j = PyList_GET_SIZE(newlist);
1052 len = PyList_GET_SIZE(self->fut_callbacks);
1053 if (j != len) {
1054 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1055 goto fail;
1056 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001057 }
1058 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001059 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001060
1061fail:
1062 Py_DECREF(newlist);
1063 return NULL;
1064}
1065
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001066/*[clinic input]
1067_asyncio.Future.cancel
1068
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001069 msg: object = None
1070
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001071Cancel the future and schedule callbacks.
1072
1073If the future is already done or cancelled, return False. Otherwise,
1074change the future's state to cancelled, schedule the callbacks and
1075return True.
1076[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001077
1078static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001079_asyncio_Future_cancel_impl(FutureObj *self, PyObject *msg)
1080/*[clinic end generated code: output=3edebbc668e5aba3 input=925eb545251f2c5a]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001081{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001082 ENSURE_FUTURE_ALIVE(self)
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001083 return future_cancel(self, msg);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001084}
1085
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001086/*[clinic input]
1087_asyncio.Future.cancelled
1088
1089Return True if the future was cancelled.
1090[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001091
1092static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001093_asyncio_Future_cancelled_impl(FutureObj *self)
1094/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001095{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001096 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001097 Py_RETURN_TRUE;
1098 }
1099 else {
1100 Py_RETURN_FALSE;
1101 }
1102}
1103
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001104/*[clinic input]
1105_asyncio.Future.done
1106
1107Return True if the future is done.
1108
1109Done means either that a result / exception are available, or that the
1110future was cancelled.
1111[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001112
1113static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001114_asyncio_Future_done_impl(FutureObj *self)
1115/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001116{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001117 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001118 Py_RETURN_FALSE;
1119 }
1120 else {
1121 Py_RETURN_TRUE;
1122 }
1123}
1124
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001125/*[clinic input]
1126_asyncio.Future.get_loop
1127
1128Return the event loop the Future is bound to.
1129[clinic start generated code]*/
1130
1131static PyObject *
1132_asyncio_Future_get_loop_impl(FutureObj *self)
1133/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1134{
Andrew Svetlovdad6be52019-11-13 23:36:46 +02001135 ENSURE_FUTURE_ALIVE(self)
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001136 Py_INCREF(self->fut_loop);
1137 return self->fut_loop;
1138}
1139
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001140static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001141FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001142{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001143 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001144 Py_RETURN_TRUE;
1145 }
1146 else {
1147 Py_RETURN_FALSE;
1148 }
1149}
1150
1151static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001152FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001153{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001154 if (future_ensure_alive(fut)) {
1155 return -1;
1156 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001157 if (val == NULL) {
1158 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1159 return -1;
1160 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001161
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001162 int is_true = PyObject_IsTrue(val);
1163 if (is_true < 0) {
1164 return -1;
1165 }
1166 fut->fut_blocking = is_true;
1167 return 0;
1168}
1169
1170static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001171FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001172{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001173 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001174 if (fut->fut_log_tb) {
1175 Py_RETURN_TRUE;
1176 }
1177 else {
1178 Py_RETURN_FALSE;
1179 }
1180}
1181
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001182static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001183FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001184{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001185 if (val == NULL) {
1186 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1187 return -1;
1188 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001189 int is_true = PyObject_IsTrue(val);
1190 if (is_true < 0) {
1191 return -1;
1192 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001193 if (is_true) {
1194 PyErr_SetString(PyExc_ValueError,
1195 "_log_traceback can only be set to False");
1196 return -1;
1197 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001198 fut->fut_log_tb = is_true;
1199 return 0;
1200}
1201
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001202static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001203FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001204{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001205 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001206 Py_RETURN_NONE;
1207 }
1208 Py_INCREF(fut->fut_loop);
1209 return fut->fut_loop;
1210}
1211
1212static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001213FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001214{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001215 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001216
1217 ENSURE_FUTURE_ALIVE(fut)
1218
Yury Selivanovf23746a2018-01-22 19:11:18 -05001219 if (fut->fut_callback0 == NULL) {
1220 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001221 Py_RETURN_NONE;
1222 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001223
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001224 Py_INCREF(fut->fut_callbacks);
1225 return fut->fut_callbacks;
1226 }
1227
Yury Selivanovf23746a2018-01-22 19:11:18 -05001228 Py_ssize_t len = 1;
1229 if (fut->fut_callbacks != NULL) {
1230 len += PyList_GET_SIZE(fut->fut_callbacks);
1231 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001232
Yury Selivanovf23746a2018-01-22 19:11:18 -05001233
1234 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001235 if (new_list == NULL) {
1236 return NULL;
1237 }
1238
Yury Selivanovf23746a2018-01-22 19:11:18 -05001239 PyObject *tup0 = PyTuple_New(2);
1240 if (tup0 == NULL) {
1241 Py_DECREF(new_list);
1242 return NULL;
1243 }
1244
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001245 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001246 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1247 assert(fut->fut_context0 != NULL);
1248 Py_INCREF(fut->fut_context0);
1249 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1250
1251 PyList_SET_ITEM(new_list, 0, tup0);
1252
1253 if (fut->fut_callbacks != NULL) {
1254 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1255 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1256 Py_INCREF(cb);
1257 PyList_SET_ITEM(new_list, i + 1, cb);
1258 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001259 }
1260
1261 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001262}
1263
1264static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001265FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001266{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001267 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001268 if (fut->fut_result == NULL) {
1269 Py_RETURN_NONE;
1270 }
1271 Py_INCREF(fut->fut_result);
1272 return fut->fut_result;
1273}
1274
1275static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001276FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001277{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001278 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001279 if (fut->fut_exception == NULL) {
1280 Py_RETURN_NONE;
1281 }
1282 Py_INCREF(fut->fut_exception);
1283 return fut->fut_exception;
1284}
1285
1286static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001287FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001288{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001289 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001290 Py_RETURN_NONE;
1291 }
1292 Py_INCREF(fut->fut_source_tb);
1293 return fut->fut_source_tb;
1294}
1295
1296static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001297FutureObj_get_cancel_message(FutureObj *fut, void *Py_UNUSED(ignored))
1298{
1299 if (fut->fut_cancel_msg == NULL) {
1300 Py_RETURN_NONE;
1301 }
1302 Py_INCREF(fut->fut_cancel_msg);
1303 return fut->fut_cancel_msg;
1304}
1305
1306static int
1307FutureObj_set_cancel_message(FutureObj *fut, PyObject *msg,
1308 void *Py_UNUSED(ignored))
1309{
1310 if (msg == NULL) {
1311 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1312 return -1;
1313 }
1314 Py_INCREF(msg);
1315 Py_XSETREF(fut->fut_cancel_msg, msg);
1316 return 0;
1317}
1318
1319static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001320FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001321{
1322 _Py_IDENTIFIER(PENDING);
1323 _Py_IDENTIFIER(CANCELLED);
1324 _Py_IDENTIFIER(FINISHED);
1325 PyObject *ret = NULL;
1326
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001327 ENSURE_FUTURE_ALIVE(fut)
1328
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001329 switch (fut->fut_state) {
1330 case STATE_PENDING:
1331 ret = _PyUnicode_FromId(&PyId_PENDING);
1332 break;
1333 case STATE_CANCELLED:
1334 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1335 break;
1336 case STATE_FINISHED:
1337 ret = _PyUnicode_FromId(&PyId_FINISHED);
1338 break;
1339 default:
1340 assert (0);
1341 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001342 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001343 return ret;
1344}
1345
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001346/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001347_asyncio.Future._make_cancelled_error
1348
1349Create the CancelledError to raise if the Future is cancelled.
1350
1351This should only be called once when handling a cancellation since
1352it erases the context exception value.
1353[clinic start generated code]*/
1354
1355static PyObject *
1356_asyncio_Future__make_cancelled_error_impl(FutureObj *self)
1357/*[clinic end generated code: output=a5df276f6c1213de input=ac6effe4ba795ecc]*/
1358{
1359 PyObject *exc = create_cancelled_error(self->fut_cancel_msg);
1360 _PyErr_StackItem *exc_state = &self->fut_cancelled_exc_state;
1361 /* Transfer ownership of exc_value from exc_state to exc since we are
1362 done with it. */
1363 PyException_SetContext(exc, exc_state->exc_value);
1364 exc_state->exc_value = NULL;
1365
1366 return exc;
1367}
1368
1369/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001370_asyncio.Future._repr_info
1371[clinic start generated code]*/
1372
1373static PyObject *
1374_asyncio_Future__repr_info_impl(FutureObj *self)
1375/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001376{
Petr Viktorinffd97532020-02-11 17:46:57 +01001377 return PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001378}
1379
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001380static PyObject *
1381FutureObj_repr(FutureObj *fut)
1382{
1383 _Py_IDENTIFIER(_repr_info);
1384
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001385 ENSURE_FUTURE_ALIVE(fut)
1386
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001387 PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
1388 &PyId__repr_info);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001389 if (rinfo == NULL) {
1390 return NULL;
1391 }
1392
Serhiy Storchakabca49392017-09-03 08:10:14 +03001393 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001394 Py_DECREF(rinfo);
1395 if (rinfo_s == NULL) {
1396 return NULL;
1397 }
1398
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001399 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1400 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001401 Py_DECREF(rinfo_s);
1402 return rstr;
1403}
1404
1405static void
1406FutureObj_finalize(FutureObj *fut)
1407{
1408 _Py_IDENTIFIER(call_exception_handler);
1409 _Py_IDENTIFIER(message);
1410 _Py_IDENTIFIER(exception);
1411 _Py_IDENTIFIER(future);
1412 _Py_IDENTIFIER(source_traceback);
1413
Serhiy Storchakabca49392017-09-03 08:10:14 +03001414 PyObject *error_type, *error_value, *error_traceback;
1415 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001416 PyObject *message = NULL;
1417 PyObject *func;
1418
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001419 if (!fut->fut_log_tb) {
1420 return;
1421 }
1422 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001423 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001424
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001425 /* Save the current exception, if any. */
1426 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1427
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001428 context = PyDict_New();
1429 if (context == NULL) {
1430 goto finally;
1431 }
1432
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001433 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001434 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001435 if (message == NULL) {
1436 goto finally;
1437 }
1438
1439 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1440 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1441 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1442 goto finally;
1443 }
1444 if (fut->fut_source_tb != NULL) {
1445 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1446 fut->fut_source_tb) < 0) {
1447 goto finally;
1448 }
1449 }
1450
1451 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1452 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01001453 PyObject *res = PyObject_CallOneArg(func, context);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001454 if (res == NULL) {
1455 PyErr_WriteUnraisable(func);
1456 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001457 else {
1458 Py_DECREF(res);
1459 }
1460 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001461 }
1462
1463finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001464 Py_XDECREF(context);
1465 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001466
1467 /* Restore the saved exception. */
1468 PyErr_Restore(error_type, error_value, error_traceback);
1469}
1470
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001471static PyObject *
1472future_cls_getitem(PyObject *cls, PyObject *type)
1473{
1474 Py_INCREF(cls);
1475 return cls;
1476}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001477
1478static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001479 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001480 0, /* am_aiter */
1481 0 /* am_anext */
1482};
1483
1484static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001485 _ASYNCIO_FUTURE_RESULT_METHODDEF
1486 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1487 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1488 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1489 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1490 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1491 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1492 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1493 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001494 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001495 _ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001496 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001497 {"__class_getitem__", future_cls_getitem, METH_O|METH_CLASS, NULL},
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001498 {NULL, NULL} /* Sentinel */
1499};
1500
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001501#define FUTURE_COMMON_GETSETLIST \
1502 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1503 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1504 (setter)FutureObj_set_blocking, NULL}, \
1505 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1506 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1507 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1508 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001509 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1510 (setter)FutureObj_set_log_traceback, NULL}, \
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001511 {"_source_traceback", (getter)FutureObj_get_source_traceback, \
1512 NULL, NULL}, \
1513 {"_cancel_message", (getter)FutureObj_get_cancel_message, \
1514 (setter)FutureObj_set_cancel_message, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001515
1516static PyGetSetDef FutureType_getsetlist[] = {
1517 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001518 {NULL} /* Sentinel */
1519};
1520
1521static void FutureObj_dealloc(PyObject *self);
1522
1523static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001524 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001525 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001526 sizeof(FutureObj), /* tp_basicsize */
1527 .tp_dealloc = FutureObj_dealloc,
1528 .tp_as_async = &FutureType_as_async,
1529 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001530 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001531 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001532 .tp_traverse = (traverseproc)FutureObj_traverse,
1533 .tp_clear = (inquiry)FutureObj_clear,
1534 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001535 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001536 .tp_methods = FutureType_methods,
1537 .tp_getset = FutureType_getsetlist,
1538 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001539 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001540 .tp_new = PyType_GenericNew,
1541 .tp_finalize = (destructor)FutureObj_finalize,
1542};
1543
1544static void
1545FutureObj_dealloc(PyObject *self)
1546{
1547 FutureObj *fut = (FutureObj *)self;
1548
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001549 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001550 /* When fut is subclass of Future, finalizer is called from
1551 * subtype_dealloc.
1552 */
1553 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1554 // resurrected.
1555 return;
1556 }
1557 }
1558
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001559 PyObject_GC_UnTrack(self);
1560
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001561 if (fut->fut_weakreflist != NULL) {
1562 PyObject_ClearWeakRefs(self);
1563 }
1564
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001565 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001566 Py_TYPE(fut)->tp_free(fut);
1567}
1568
1569
1570/*********************** Future Iterator **************************/
1571
1572typedef struct {
1573 PyObject_HEAD
1574 FutureObj *future;
1575} futureiterobject;
1576
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001577
1578#define FI_FREELIST_MAXLEN 255
1579static futureiterobject *fi_freelist = NULL;
1580static Py_ssize_t fi_freelist_len = 0;
1581
1582
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001583static void
1584FutureIter_dealloc(futureiterobject *it)
1585{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001586 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001587 Py_CLEAR(it->future);
1588
1589 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1590 fi_freelist_len++;
1591 it->future = (FutureObj*) fi_freelist;
1592 fi_freelist = it;
1593 }
1594 else {
1595 PyObject_GC_Del(it);
1596 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001597}
1598
1599static PyObject *
1600FutureIter_iternext(futureiterobject *it)
1601{
1602 PyObject *res;
1603 FutureObj *fut = it->future;
1604
1605 if (fut == NULL) {
1606 return NULL;
1607 }
1608
1609 if (fut->fut_state == STATE_PENDING) {
1610 if (!fut->fut_blocking) {
1611 fut->fut_blocking = 1;
1612 Py_INCREF(fut);
1613 return (PyObject *)fut;
1614 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001615 PyErr_SetString(PyExc_RuntimeError,
1616 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001617 return NULL;
1618 }
1619
Serhiy Storchakabca49392017-09-03 08:10:14 +03001620 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001621 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001622 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001623 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001624 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001625 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001626 }
1627
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001628 Py_DECREF(fut);
1629 return NULL;
1630}
1631
1632static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001633FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001634{
INADA Naoki74c17532016-10-25 19:00:45 +09001635 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001636 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001637 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001638 return FutureIter_iternext(self);
1639}
1640
1641static PyObject *
1642FutureIter_throw(futureiterobject *self, PyObject *args)
1643{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001644 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001645 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1646 return NULL;
1647
1648 if (val == Py_None) {
1649 val = NULL;
1650 }
1651 if (tb == Py_None) {
1652 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001653 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1654 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1655 return NULL;
1656 }
1657
1658 Py_INCREF(type);
1659 Py_XINCREF(val);
1660 Py_XINCREF(tb);
1661
1662 if (PyExceptionClass_Check(type)) {
1663 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001664 /* No need to call PyException_SetTraceback since we'll be calling
1665 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001666 } else if (PyExceptionInstance_Check(type)) {
1667 if (val) {
1668 PyErr_SetString(PyExc_TypeError,
1669 "instance exception may not have a separate value");
1670 goto fail;
1671 }
1672 val = type;
1673 type = PyExceptionInstance_Class(type);
1674 Py_INCREF(type);
1675 if (tb == NULL)
1676 tb = PyException_GetTraceback(val);
1677 } else {
1678 PyErr_SetString(PyExc_TypeError,
1679 "exceptions must be classes deriving BaseException or "
1680 "instances of such a class");
1681 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001682 }
1683
1684 Py_CLEAR(self->future);
1685
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001686 PyErr_Restore(type, val, tb);
1687
Serhiy Storchakabca49392017-09-03 08:10:14 +03001688 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001689
1690 fail:
1691 Py_DECREF(type);
1692 Py_XDECREF(val);
1693 Py_XDECREF(tb);
1694 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001695}
1696
1697static PyObject *
1698FutureIter_close(futureiterobject *self, PyObject *arg)
1699{
1700 Py_CLEAR(self->future);
1701 Py_RETURN_NONE;
1702}
1703
1704static int
1705FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1706{
1707 Py_VISIT(it->future);
1708 return 0;
1709}
1710
1711static PyMethodDef FutureIter_methods[] = {
1712 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1713 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1714 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1715 {NULL, NULL} /* Sentinel */
1716};
1717
1718static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001719 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001720 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001721 .tp_basicsize = sizeof(futureiterobject),
1722 .tp_itemsize = 0,
1723 .tp_dealloc = (destructor)FutureIter_dealloc,
1724 .tp_getattro = PyObject_GenericGetAttr,
1725 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1726 .tp_traverse = (traverseproc)FutureIter_traverse,
1727 .tp_iter = PyObject_SelfIter,
1728 .tp_iternext = (iternextfunc)FutureIter_iternext,
1729 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001730};
1731
1732static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001733future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001734{
1735 futureiterobject *it;
1736
1737 if (!PyObject_TypeCheck(fut, &FutureType)) {
1738 PyErr_BadInternalCall();
1739 return NULL;
1740 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001741
1742 ENSURE_FUTURE_ALIVE(fut)
1743
1744 if (fi_freelist_len) {
1745 fi_freelist_len--;
1746 it = fi_freelist;
1747 fi_freelist = (futureiterobject*) it->future;
1748 it->future = NULL;
1749 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001750 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001751 else {
1752 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1753 if (it == NULL) {
1754 return NULL;
1755 }
1756 }
1757
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001758 Py_INCREF(fut);
1759 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001760 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001761 return (PyObject*)it;
1762}
1763
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001764
1765/*********************** Task **************************/
1766
1767
1768/*[clinic input]
1769class _asyncio.Task "TaskObj *" "&Task_Type"
1770[clinic start generated code]*/
1771/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1772
1773static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001774static PyObject * task_wakeup(TaskObj *, PyObject *);
1775static PyObject * task_step(TaskObj *, PyObject *);
1776
1777/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001778
INADA Naokic411a7d2016-10-18 11:48:14 +09001779static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001780TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001781{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001782 Py_CLEAR(o->sw_task);
1783 Py_CLEAR(o->sw_arg);
1784 return 0;
1785}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001786
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001787static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001788TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001789{
1790 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001791 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001792 Py_TYPE(o)->tp_free(o);
1793}
1794
1795static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001796TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001797 PyObject *args, PyObject *kwds)
1798{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001799 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1800 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1801 return NULL;
1802 }
1803 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1804 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1805 return NULL;
1806 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001807 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001808}
1809
1810static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001811TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001812 visitproc visit, void *arg)
1813{
1814 Py_VISIT(o->sw_task);
1815 Py_VISIT(o->sw_arg);
1816 return 0;
1817}
1818
1819static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001820TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001821{
1822 if (o->sw_task) {
1823 Py_INCREF(o->sw_task);
1824 return (PyObject*)o->sw_task;
1825 }
1826 Py_RETURN_NONE;
1827}
1828
Serhiy Storchakabca49392017-09-03 08:10:14 +03001829static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1830 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001831 {NULL} /* Sentinel */
1832};
1833
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001834static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001835 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001836 "TaskStepMethWrapper",
1837 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001838 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001839 .tp_getset = TaskStepMethWrapper_getsetlist,
1840 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1841 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001842 .tp_getattro = PyObject_GenericGetAttr,
1843 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001844 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1845 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001846};
1847
1848static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001849TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001850{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001851 TaskStepMethWrapper *o;
1852 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001853 if (o == NULL) {
1854 return NULL;
1855 }
1856
1857 Py_INCREF(task);
1858 o->sw_task = task;
1859
1860 Py_XINCREF(arg);
1861 o->sw_arg = arg;
1862
1863 PyObject_GC_Track(o);
1864 return (PyObject*) o;
1865}
1866
1867/* ----- Task._wakeup wrapper */
1868
1869static PyObject *
1870TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1871 PyObject *args, PyObject *kwds)
1872{
1873 PyObject *fut;
1874
Serhiy Storchakabca49392017-09-03 08:10:14 +03001875 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1876 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1877 return NULL;
1878 }
1879 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001880 return NULL;
1881 }
1882
Yury Selivanov22feeb82018-01-24 11:31:01 -05001883 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001884}
1885
1886static int
1887TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1888{
1889 Py_CLEAR(o->ww_task);
1890 return 0;
1891}
1892
1893static int
1894TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1895 visitproc visit, void *arg)
1896{
1897 Py_VISIT(o->ww_task);
1898 return 0;
1899}
1900
1901static void
1902TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1903{
1904 PyObject_GC_UnTrack(o);
1905 (void)TaskWakeupMethWrapper_clear(o);
1906 Py_TYPE(o)->tp_free(o);
1907}
1908
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001909static PyObject *
1910TaskWakeupMethWrapper_get___self__(TaskWakeupMethWrapper *o, void *Py_UNUSED(ignored))
1911{
1912 if (o->ww_task) {
1913 Py_INCREF(o->ww_task);
1914 return (PyObject*)o->ww_task;
1915 }
1916 Py_RETURN_NONE;
1917}
1918
1919static PyGetSetDef TaskWakeupMethWrapper_getsetlist[] = {
1920 {"__self__", (getter)TaskWakeupMethWrapper_get___self__, NULL, NULL},
1921 {NULL} /* Sentinel */
1922};
1923
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001924static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001925 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001926 "TaskWakeupMethWrapper",
1927 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1928 .tp_itemsize = 0,
1929 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1930 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1931 .tp_getattro = PyObject_GenericGetAttr,
1932 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1933 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1934 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001935 .tp_getset = TaskWakeupMethWrapper_getsetlist,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001936};
1937
1938static PyObject *
1939TaskWakeupMethWrapper_new(TaskObj *task)
1940{
1941 TaskWakeupMethWrapper *o;
1942 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1943 if (o == NULL) {
1944 return NULL;
1945 }
1946
1947 Py_INCREF(task);
1948 o->ww_task = task;
1949
1950 PyObject_GC_Track(o);
1951 return (PyObject*) o;
1952}
1953
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001954/* ----- Task introspection helpers */
1955
1956static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001957register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001958{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001959 _Py_IDENTIFIER(add);
1960
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001961 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1962 &PyId_add, task);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001963 if (res == NULL) {
1964 return -1;
1965 }
1966 Py_DECREF(res);
1967 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001968}
1969
1970
1971static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001972unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001973{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001974 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001975
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001976 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1977 &PyId_discard, task);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001978 if (res == NULL) {
1979 return -1;
1980 }
1981 Py_DECREF(res);
1982 return 0;
1983}
1984
1985
1986static int
1987enter_task(PyObject *loop, PyObject *task)
1988{
1989 PyObject *item;
1990 Py_hash_t hash;
1991 hash = PyObject_Hash(loop);
1992 if (hash == -1) {
1993 return -1;
1994 }
1995 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1996 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001997 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001998 PyErr_Format(
1999 PyExc_RuntimeError,
2000 "Cannot enter into task %R while another " \
2001 "task %R is being executed.",
2002 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002003 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002004 return -1;
2005 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03002006 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002007 return -1;
2008 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03002009 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002010}
2011
2012
2013static int
2014leave_task(PyObject *loop, PyObject *task)
2015/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
2016{
2017 PyObject *item;
2018 Py_hash_t hash;
2019 hash = PyObject_Hash(loop);
2020 if (hash == -1) {
2021 return -1;
2022 }
2023 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
2024 if (item != task) {
2025 if (item == NULL) {
2026 /* Not entered, replace with None */
2027 item = Py_None;
2028 }
2029 PyErr_Format(
2030 PyExc_RuntimeError,
2031 "Leaving task %R does not match the current task %R.",
2032 task, item, NULL);
2033 return -1;
2034 }
2035 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
2036}
2037
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002038/* ----- Task */
2039
2040/*[clinic input]
2041_asyncio.Task.__init__
2042
Serhiy Storchakabca49392017-09-03 08:10:14 +03002043 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002044 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002045 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002046 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002047
2048A coroutine wrapped in a Future.
2049[clinic start generated code]*/
2050
2051static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002052_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2053 PyObject *name)
2054/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002055{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002056 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002057 return -1;
2058 }
INADA Naokic411a7d2016-10-18 11:48:14 +09002059
Yury Selivanova9d7e552017-12-19 07:18:45 -05002060 int is_coro = is_coroutine(coro);
2061 if (is_coro == -1) {
2062 return -1;
2063 }
2064 if (is_coro == 0) {
2065 self->task_log_destroy_pending = 0;
2066 PyErr_Format(PyExc_TypeError,
2067 "a coroutine was expected, got %R",
2068 coro, NULL);
2069 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02002070 }
2071
Oren Milmand019bc82018-02-13 12:28:33 +02002072 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05002073 if (self->task_context == NULL) {
2074 return -1;
2075 }
2076
Oren Milmand019bc82018-02-13 12:28:33 +02002077 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002078 self->task_must_cancel = 0;
2079 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002080 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02002081 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002082
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002083 if (name == Py_None) {
2084 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03002085 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002086 name = PyObject_Str(name);
2087 } else {
2088 Py_INCREF(name);
2089 }
2090 Py_XSETREF(self->task_name, name);
2091 if (self->task_name == NULL) {
2092 return -1;
2093 }
2094
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002095 if (task_call_step_soon(self, NULL)) {
2096 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09002097 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002098 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002099}
2100
2101static int
2102TaskObj_clear(TaskObj *task)
2103{
2104 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002105 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002106 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002107 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002108 Py_CLEAR(task->task_fut_waiter);
2109 return 0;
2110}
2111
2112static int
2113TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2114{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002115 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002116 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002117 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002118 Py_VISIT(task->task_fut_waiter);
2119 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2120 return 0;
2121}
2122
2123static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002124TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002125{
2126 if (task->task_log_destroy_pending) {
2127 Py_RETURN_TRUE;
2128 }
2129 else {
2130 Py_RETURN_FALSE;
2131 }
2132}
2133
2134static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002135TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002136{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002137 if (val == NULL) {
2138 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2139 return -1;
2140 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002141 int is_true = PyObject_IsTrue(val);
2142 if (is_true < 0) {
2143 return -1;
2144 }
2145 task->task_log_destroy_pending = is_true;
2146 return 0;
2147}
2148
2149static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002150TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002151{
2152 if (task->task_must_cancel) {
2153 Py_RETURN_TRUE;
2154 }
2155 else {
2156 Py_RETURN_FALSE;
2157 }
2158}
2159
2160static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002161TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002162{
2163 if (task->task_coro) {
2164 Py_INCREF(task->task_coro);
2165 return task->task_coro;
2166 }
2167
2168 Py_RETURN_NONE;
2169}
2170
2171static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002172TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002173{
2174 if (task->task_fut_waiter) {
2175 Py_INCREF(task->task_fut_waiter);
2176 return task->task_fut_waiter;
2177 }
2178
2179 Py_RETURN_NONE;
2180}
2181
2182/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002183_asyncio.Task._make_cancelled_error
2184
2185Create the CancelledError to raise if the Task is cancelled.
2186
2187This should only be called once when handling a cancellation since
2188it erases the context exception value.
2189[clinic start generated code]*/
2190
2191static PyObject *
2192_asyncio_Task__make_cancelled_error_impl(TaskObj *self)
2193/*[clinic end generated code: output=55a819e8b4276fab input=52c0e32de8e2f840]*/
2194{
2195 FutureObj *fut = (FutureObj*)self;
2196 return _asyncio_Future__make_cancelled_error_impl(fut);
2197}
2198
2199
2200/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002201_asyncio.Task._repr_info
2202[clinic start generated code]*/
2203
2204static PyObject *
2205_asyncio_Task__repr_info_impl(TaskObj *self)
2206/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2207{
Petr Viktorinffd97532020-02-11 17:46:57 +01002208 return PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002209}
2210
2211/*[clinic input]
2212_asyncio.Task.cancel
2213
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002214 msg: object = None
2215
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002216Request that this task cancel itself.
2217
2218This arranges for a CancelledError to be thrown into the
2219wrapped coroutine on the next cycle through the event loop.
2220The coroutine then has a chance to clean up or even deny
2221the request using try/except/finally.
2222
2223Unlike Future.cancel, this does not guarantee that the
2224task will be cancelled: the exception might be caught and
2225acted upon, delaying cancellation of the task or preventing
2226cancellation completely. The task may also return a value or
2227raise a different exception.
2228
2229Immediately after this method is called, Task.cancelled() will
2230not return True (unless the task was already cancelled). A
2231task will be marked as cancelled when the wrapped coroutine
2232terminates with a CancelledError exception (even if cancel()
2233was not called).
2234[clinic start generated code]*/
2235
2236static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002237_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
2238/*[clinic end generated code: output=c66b60d41c74f9f1 input=f4ff8e8ffc5f1c00]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002239{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002240 self->task_log_tb = 0;
2241
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002242 if (self->task_state != STATE_PENDING) {
2243 Py_RETURN_FALSE;
2244 }
2245
2246 if (self->task_fut_waiter) {
2247 PyObject *res;
2248 int is_true;
2249
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002250 res = _PyObject_CallMethodIdOneArg(self->task_fut_waiter,
2251 &PyId_cancel, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002252 if (res == NULL) {
2253 return NULL;
2254 }
2255
2256 is_true = PyObject_IsTrue(res);
2257 Py_DECREF(res);
2258 if (is_true < 0) {
2259 return NULL;
2260 }
2261
2262 if (is_true) {
2263 Py_RETURN_TRUE;
2264 }
2265 }
2266
2267 self->task_must_cancel = 1;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002268 Py_XINCREF(msg);
2269 Py_XSETREF(self->task_cancel_msg, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002270 Py_RETURN_TRUE;
2271}
2272
2273/*[clinic input]
2274_asyncio.Task.get_stack
2275
2276 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002277 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002278
2279Return the list of stack frames for this task's coroutine.
2280
2281If the coroutine is not done, this returns the stack where it is
2282suspended. If the coroutine has completed successfully or was
2283cancelled, this returns an empty list. If the coroutine was
2284terminated by an exception, this returns the list of traceback
2285frames.
2286
2287The frames are always ordered from oldest to newest.
2288
2289The optional limit gives the maximum number of frames to
2290return; by default all available frames are returned. Its
2291meaning differs depending on whether a stack or a traceback is
2292returned: the newest frames of a stack are returned, but the
2293oldest frames of a traceback are returned. (This matches the
2294behavior of the traceback module.)
2295
2296For reasons beyond our control, only one stack frame is
2297returned for a suspended coroutine.
2298[clinic start generated code]*/
2299
2300static PyObject *
2301_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002302/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002303{
2304 return PyObject_CallFunctionObjArgs(
2305 asyncio_task_get_stack_func, self, limit, NULL);
2306}
2307
2308/*[clinic input]
2309_asyncio.Task.print_stack
2310
2311 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002312 limit: object = None
2313 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002314
2315Print the stack or traceback for this task's coroutine.
2316
2317This produces output similar to that of the traceback module,
2318for the frames retrieved by get_stack(). The limit argument
2319is passed to get_stack(). The file argument is an I/O stream
2320to which the output is written; by default output is written
2321to sys.stderr.
2322[clinic start generated code]*/
2323
2324static PyObject *
2325_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2326 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002327/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002328{
2329 return PyObject_CallFunctionObjArgs(
2330 asyncio_task_print_stack_func, self, limit, file, NULL);
2331}
2332
2333/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002334_asyncio.Task.set_result
2335
2336 result: object
2337 /
2338[clinic start generated code]*/
2339
2340static PyObject *
2341_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2342/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2343{
2344 PyErr_SetString(PyExc_RuntimeError,
2345 "Task does not support set_result operation");
2346 return NULL;
2347}
2348
2349/*[clinic input]
2350_asyncio.Task.set_exception
2351
2352 exception: object
2353 /
2354[clinic start generated code]*/
2355
2356static PyObject *
2357_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2358/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2359{
2360 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002361 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002362 return NULL;
2363}
2364
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002365/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002366_asyncio.Task.get_coro
2367[clinic start generated code]*/
2368
2369static PyObject *
2370_asyncio_Task_get_coro_impl(TaskObj *self)
2371/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2372{
2373 Py_INCREF(self->task_coro);
2374 return self->task_coro;
2375}
2376
2377/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002378_asyncio.Task.get_name
2379[clinic start generated code]*/
2380
2381static PyObject *
2382_asyncio_Task_get_name_impl(TaskObj *self)
2383/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2384{
2385 if (self->task_name) {
2386 Py_INCREF(self->task_name);
2387 return self->task_name;
2388 }
2389
2390 Py_RETURN_NONE;
2391}
2392
2393/*[clinic input]
2394_asyncio.Task.set_name
2395
2396 value: object
2397 /
2398[clinic start generated code]*/
2399
2400static PyObject *
2401_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2402/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2403{
Alex Grönholma7548232018-08-09 23:49:49 +03002404 if (!PyUnicode_CheckExact(value)) {
2405 value = PyObject_Str(value);
2406 if (value == NULL) {
2407 return NULL;
2408 }
2409 } else {
2410 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002411 }
2412
Alex Grönholma7548232018-08-09 23:49:49 +03002413 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002414 Py_RETURN_NONE;
2415}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002416
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002417static void
2418TaskObj_finalize(TaskObj *task)
2419{
2420 _Py_IDENTIFIER(call_exception_handler);
2421 _Py_IDENTIFIER(task);
2422 _Py_IDENTIFIER(message);
2423 _Py_IDENTIFIER(source_traceback);
2424
Serhiy Storchakabca49392017-09-03 08:10:14 +03002425 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002426 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002427 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002428 PyObject *error_type, *error_value, *error_traceback;
2429
2430 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2431 goto done;
2432 }
2433
2434 /* Save the current exception, if any. */
2435 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2436
2437 context = PyDict_New();
2438 if (context == NULL) {
2439 goto finally;
2440 }
2441
2442 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2443 if (message == NULL) {
2444 goto finally;
2445 }
2446
2447 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2448 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2449 {
2450 goto finally;
2451 }
2452
2453 if (task->task_source_tb != NULL) {
2454 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2455 task->task_source_tb) < 0)
2456 {
2457 goto finally;
2458 }
2459 }
2460
2461 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2462 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01002463 PyObject *res = PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002464 if (res == NULL) {
2465 PyErr_WriteUnraisable(func);
2466 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002467 else {
2468 Py_DECREF(res);
2469 }
2470 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002471 }
2472
2473finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002474 Py_XDECREF(context);
2475 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002476
2477 /* Restore the saved exception. */
2478 PyErr_Restore(error_type, error_value, error_traceback);
2479
2480done:
2481 FutureObj_finalize((FutureObj*)task);
2482}
2483
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002484static PyObject *
2485task_cls_getitem(PyObject *cls, PyObject *type)
2486{
2487 Py_INCREF(cls);
2488 return cls;
2489}
2490
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002491static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2492
2493static PyMethodDef TaskType_methods[] = {
2494 _ASYNCIO_FUTURE_RESULT_METHODDEF
2495 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002496 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2497 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2498 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2499 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002500 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2501 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002502 _ASYNCIO_TASK_CANCEL_METHODDEF
2503 _ASYNCIO_TASK_GET_STACK_METHODDEF
2504 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002505 _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002506 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002507 _ASYNCIO_TASK_GET_NAME_METHODDEF
2508 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002509 _ASYNCIO_TASK_GET_CORO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002510 {"__class_getitem__", task_cls_getitem, METH_O|METH_CLASS, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002511 {NULL, NULL} /* Sentinel */
2512};
2513
2514static PyGetSetDef TaskType_getsetlist[] = {
2515 FUTURE_COMMON_GETSETLIST
2516 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2517 (setter)TaskObj_set_log_destroy_pending, NULL},
2518 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2519 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2520 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2521 {NULL} /* Sentinel */
2522};
2523
2524static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002525 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002526 "_asyncio.Task",
2527 sizeof(TaskObj), /* tp_basicsize */
2528 .tp_base = &FutureType,
2529 .tp_dealloc = TaskObj_dealloc,
2530 .tp_as_async = &FutureType_as_async,
2531 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002532 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002533 .tp_doc = _asyncio_Task___init____doc__,
2534 .tp_traverse = (traverseproc)TaskObj_traverse,
2535 .tp_clear = (inquiry)TaskObj_clear,
2536 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2537 .tp_iter = (getiterfunc)future_new_iter,
2538 .tp_methods = TaskType_methods,
2539 .tp_getset = TaskType_getsetlist,
2540 .tp_dictoffset = offsetof(TaskObj, dict),
2541 .tp_init = (initproc)_asyncio_Task___init__,
2542 .tp_new = PyType_GenericNew,
2543 .tp_finalize = (destructor)TaskObj_finalize,
2544};
2545
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002546static void
2547TaskObj_dealloc(PyObject *self)
2548{
2549 TaskObj *task = (TaskObj *)self;
2550
2551 if (Task_CheckExact(self)) {
2552 /* When fut is subclass of Task, finalizer is called from
2553 * subtype_dealloc.
2554 */
2555 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2556 // resurrected.
2557 return;
2558 }
2559 }
2560
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002561 PyObject_GC_UnTrack(self);
2562
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002563 if (task->task_weakreflist != NULL) {
2564 PyObject_ClearWeakRefs(self);
2565 }
2566
2567 (void)TaskObj_clear(task);
2568 Py_TYPE(task)->tp_free(task);
2569}
2570
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002571static int
2572task_call_step_soon(TaskObj *task, PyObject *arg)
2573{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002574 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002575 if (cb == NULL) {
2576 return -1;
2577 }
2578
Yury Selivanovf23746a2018-01-22 19:11:18 -05002579 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002580 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002581 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002582}
2583
2584static PyObject *
2585task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2586{
2587 PyObject* msg;
2588
2589 va_list vargs;
2590#ifdef HAVE_STDARG_PROTOTYPES
2591 va_start(vargs, format);
2592#else
2593 va_start(vargs);
2594#endif
2595 msg = PyUnicode_FromFormatV(format, vargs);
2596 va_end(vargs);
2597
2598 if (msg == NULL) {
2599 return NULL;
2600 }
2601
Petr Viktorinffd97532020-02-11 17:46:57 +01002602 PyObject *e = PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002603 Py_DECREF(msg);
2604 if (e == NULL) {
2605 return NULL;
2606 }
2607
2608 if (task_call_step_soon(task, e) == -1) {
2609 Py_DECREF(e);
2610 return NULL;
2611 }
2612
2613 Py_DECREF(e);
2614 Py_RETURN_NONE;
2615}
2616
2617static PyObject *
2618task_step_impl(TaskObj *task, PyObject *exc)
2619{
2620 int res;
2621 int clear_exc = 0;
2622 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002623 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002624 PyObject *o;
2625
2626 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002627 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002628 "_step(): already done: %R %R",
2629 task,
2630 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002631 goto fail;
2632 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002633
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002634 if (task->task_must_cancel) {
2635 assert(exc != Py_None);
2636
2637 if (exc) {
2638 /* Check if exc is a CancelledError */
2639 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2640 if (res == -1) {
2641 /* An error occurred, abort */
2642 goto fail;
2643 }
2644 if (res == 0) {
2645 /* exc is not CancelledError; reset it to NULL */
2646 exc = NULL;
2647 }
2648 }
2649
2650 if (!exc) {
2651 /* exc was not a CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002652 exc = create_cancelled_error(task->task_cancel_msg);
2653
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002654 if (!exc) {
2655 goto fail;
2656 }
2657 clear_exc = 1;
2658 }
2659
2660 task->task_must_cancel = 0;
2661 }
2662
2663 Py_CLEAR(task->task_fut_waiter);
2664
Serhiy Storchakabca49392017-09-03 08:10:14 +03002665 coro = task->task_coro;
2666 if (coro == NULL) {
2667 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
Chris Jerdonekd2c349b2020-05-08 03:54:38 -07002668 if (clear_exc) {
2669 /* We created 'exc' during this call */
2670 Py_DECREF(exc);
2671 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002672 return NULL;
2673 }
2674
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002675 if (exc == NULL) {
2676 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2677 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2678 }
2679 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002680 result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002681 }
2682 }
2683 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002684 result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002685 if (clear_exc) {
2686 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002687 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002688 }
2689 }
2690
2691 if (result == NULL) {
2692 PyObject *et, *ev, *tb;
2693
2694 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2695 /* The error is StopIteration and that means that
2696 the underlying coroutine has resolved */
Yury Selivanovedad4d82019-09-25 03:32:08 -07002697
2698 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002699 if (task->task_must_cancel) {
2700 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002701 task->task_must_cancel = 0;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002702 res = future_cancel((FutureObj*)task, task->task_cancel_msg);
INADA Naoki991adca2017-05-11 21:18:38 +09002703 }
Yury Selivanovedad4d82019-09-25 03:32:08 -07002704 else {
2705 res = future_set_result((FutureObj*)task, o);
2706 }
2707
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002708 Py_DECREF(o);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002709
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002710 if (res == NULL) {
2711 return NULL;
2712 }
2713 Py_DECREF(res);
2714 Py_RETURN_NONE;
2715 }
2716
2717 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2718 /* CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002719 PyErr_Fetch(&et, &ev, &tb);
2720
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002721 FutureObj *fut = (FutureObj*)task;
2722 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
2723 exc_state->exc_type = et;
2724 exc_state->exc_value = ev;
2725 exc_state->exc_traceback = tb;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002726
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002727 return future_cancel(fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002728 }
2729
2730 /* Some other exception; pop it and call Task.set_exception() */
2731 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002732
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002733 assert(et);
2734 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2735 PyErr_NormalizeException(&et, &ev, &tb);
2736 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002737 if (tb != NULL) {
2738 PyException_SetTraceback(ev, tb);
2739 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002740 o = future_set_exception((FutureObj*)task, ev);
2741 if (!o) {
2742 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002743 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002744 Py_XDECREF(tb);
2745 Py_XDECREF(ev);
2746 goto fail;
2747 }
2748 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002749 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002750
Yury Selivanov431b5402019-05-27 14:45:12 +02002751 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2752 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2753 {
2754 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002755 PyErr_Restore(et, ev, tb);
2756 goto fail;
2757 }
2758
Serhiy Storchakabca49392017-09-03 08:10:14 +03002759 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002760 Py_XDECREF(tb);
2761 Py_XDECREF(ev);
2762
2763 Py_RETURN_NONE;
2764 }
2765
2766 if (result == (PyObject*)task) {
2767 /* We have a task that wants to await on itself */
2768 goto self_await;
2769 }
2770
2771 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2772 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2773 PyObject *wrapper;
2774 PyObject *res;
2775 FutureObj *fut = (FutureObj*)result;
2776
2777 /* Check if `result` future is attached to a different loop */
2778 if (fut->fut_loop != task->task_loop) {
2779 goto different_loop;
2780 }
2781
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002782 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002783 goto yield_insteadof_yf;
2784 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002785
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002786 fut->fut_blocking = 0;
2787
2788 /* result.add_done_callback(task._wakeup) */
2789 wrapper = TaskWakeupMethWrapper_new(task);
2790 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002791 goto fail;
2792 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002793 res = future_add_done_callback(
2794 (FutureObj*)result, wrapper, task->task_context);
2795 Py_DECREF(wrapper);
2796 if (res == NULL) {
2797 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002798 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002799 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002800
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002801 /* task._fut_waiter = result */
2802 task->task_fut_waiter = result; /* no incref is necessary */
2803
2804 if (task->task_must_cancel) {
2805 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002806 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002807 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2808 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002809 if (r == NULL) {
2810 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002811 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002812 is_true = PyObject_IsTrue(r);
2813 Py_DECREF(r);
2814 if (is_true < 0) {
2815 return NULL;
2816 }
2817 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002818 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002819 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002820 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002821
2822 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002823 }
2824
2825 /* Check if `result` is None */
2826 if (result == Py_None) {
2827 /* Bare yield relinquishes control for one event loop iteration. */
2828 if (task_call_step_soon(task, NULL)) {
2829 goto fail;
2830 }
2831 return result;
2832 }
2833
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002834 /* Check if `result` is a Future-compatible object */
2835 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2836 goto fail;
2837 }
2838 if (o != NULL && o != Py_None) {
2839 /* `result` is a Future-compatible object */
2840 PyObject *wrapper;
2841 PyObject *res;
2842
2843 int blocking = PyObject_IsTrue(o);
2844 Py_DECREF(o);
2845 if (blocking < 0) {
2846 goto fail;
2847 }
2848
2849 /* Check if `result` future is attached to a different loop */
2850 PyObject *oloop = get_future_loop(result);
2851 if (oloop == NULL) {
2852 goto fail;
2853 }
2854 if (oloop != task->task_loop) {
2855 Py_DECREF(oloop);
2856 goto different_loop;
2857 }
2858 Py_DECREF(oloop);
2859
2860 if (!blocking) {
2861 goto yield_insteadof_yf;
2862 }
2863
2864 /* result._asyncio_future_blocking = False */
2865 if (_PyObject_SetAttrId(
2866 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2867 goto fail;
2868 }
2869
2870 wrapper = TaskWakeupMethWrapper_new(task);
2871 if (wrapper == NULL) {
2872 goto fail;
2873 }
2874
2875 /* result.add_done_callback(task._wakeup) */
2876 PyObject *add_cb = _PyObject_GetAttrId(
2877 result, &PyId_add_done_callback);
2878 if (add_cb == NULL) {
2879 Py_DECREF(wrapper);
2880 goto fail;
2881 }
2882 PyObject *stack[2];
2883 stack[0] = wrapper;
2884 stack[1] = (PyObject *)task->task_context;
Petr Viktorinffd97532020-02-11 17:46:57 +01002885 res = PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002886 Py_DECREF(add_cb);
2887 Py_DECREF(wrapper);
2888 if (res == NULL) {
2889 goto fail;
2890 }
2891 Py_DECREF(res);
2892
2893 /* task._fut_waiter = result */
2894 task->task_fut_waiter = result; /* no incref is necessary */
2895
2896 if (task->task_must_cancel) {
2897 PyObject *r;
2898 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002899 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2900 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002901 if (r == NULL) {
2902 return NULL;
2903 }
2904 is_true = PyObject_IsTrue(r);
2905 Py_DECREF(r);
2906 if (is_true < 0) {
2907 return NULL;
2908 }
2909 else if (is_true) {
2910 task->task_must_cancel = 0;
2911 }
2912 }
2913
2914 Py_RETURN_NONE;
2915 }
2916
2917 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002918 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002919 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
2920 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002921 goto fail;
2922 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002923 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002924 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002925 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002926 task, PyExc_RuntimeError,
2927 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03002928 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002929 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002930 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002931 }
2932
2933 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03002934 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002935 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002936 Py_DECREF(result);
2937 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002938
2939self_await:
2940 o = task_set_error_soon(
2941 task, PyExc_RuntimeError,
2942 "Task cannot await on itself: %R", task);
2943 Py_DECREF(result);
2944 return o;
2945
2946yield_insteadof_yf:
2947 o = task_set_error_soon(
2948 task, PyExc_RuntimeError,
2949 "yield was used instead of yield from "
2950 "in task %R with %R",
2951 task, result);
2952 Py_DECREF(result);
2953 return o;
2954
2955different_loop:
2956 o = task_set_error_soon(
2957 task, PyExc_RuntimeError,
2958 "Task %R got Future %R attached to a different loop",
2959 task, result);
2960 Py_DECREF(result);
2961 return o;
2962
2963fail:
2964 Py_XDECREF(result);
2965 return NULL;
2966}
2967
2968static PyObject *
2969task_step(TaskObj *task, PyObject *exc)
2970{
2971 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002972
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002973 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002974 return NULL;
2975 }
2976
2977 res = task_step_impl(task, exc);
2978
2979 if (res == NULL) {
2980 PyObject *et, *ev, *tb;
2981 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002982 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002983 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002984 return NULL;
2985 }
2986 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002987 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002988 Py_DECREF(res);
2989 return NULL;
2990 }
2991 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002992 return res;
2993 }
2994 }
2995}
2996
2997static PyObject *
2998task_wakeup(TaskObj *task, PyObject *o)
2999{
Serhiy Storchakabca49392017-09-03 08:10:14 +03003000 PyObject *et, *ev, *tb;
3001 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003002 assert(o);
3003
3004 if (Future_CheckExact(o) || Task_CheckExact(o)) {
3005 PyObject *fut_result = NULL;
3006 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003007
3008 switch(res) {
3009 case -1:
3010 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003011 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003012 case 0:
3013 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003014 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003015 default:
3016 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003017 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003018 Py_DECREF(fut_result);
3019 return result;
3020 }
3021 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003022 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03003023 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
3024 if (fut_result != NULL) {
3025 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003026 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003027 }
3028 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003029 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003030
3031 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003032 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
3033 PyErr_NormalizeException(&et, &ev, &tb);
3034 }
3035
Yury Selivanov22feeb82018-01-24 11:31:01 -05003036 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003037
3038 Py_DECREF(et);
3039 Py_XDECREF(tb);
3040 Py_XDECREF(ev);
3041
3042 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003043}
3044
3045
Yury Selivanova70232f2017-12-13 14:49:42 -05003046/*********************** Functions **************************/
3047
3048
3049/*[clinic input]
3050_asyncio._get_running_loop
3051
3052Return the running event loop or None.
3053
3054This is a low-level function intended to be used by event loops.
3055This function is thread-specific.
3056
3057[clinic start generated code]*/
3058
3059static PyObject *
3060_asyncio__get_running_loop_impl(PyObject *module)
3061/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3062{
3063 PyObject *loop;
3064 if (get_running_loop(&loop)) {
3065 return NULL;
3066 }
3067 if (loop == NULL) {
3068 /* There's no currently running event loop */
3069 Py_RETURN_NONE;
3070 }
3071 return loop;
3072}
3073
3074/*[clinic input]
3075_asyncio._set_running_loop
3076 loop: 'O'
3077 /
3078
3079Set the running event loop.
3080
3081This is a low-level function intended to be used by event loops.
3082This function is thread-specific.
3083[clinic start generated code]*/
3084
3085static PyObject *
3086_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3087/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3088{
3089 if (set_running_loop(loop)) {
3090 return NULL;
3091 }
3092 Py_RETURN_NONE;
3093}
3094
3095/*[clinic input]
3096_asyncio.get_event_loop
3097
3098Return an asyncio event loop.
3099
3100When called from a coroutine or a callback (e.g. scheduled with
3101call_soon or similar API), this function will always return the
3102running event loop.
3103
3104If there is no running event loop set, the function will return
3105the result of `get_event_loop_policy().get_event_loop()` call.
3106[clinic start generated code]*/
3107
3108static PyObject *
3109_asyncio_get_event_loop_impl(PyObject *module)
3110/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3111{
3112 return get_event_loop();
3113}
3114
3115/*[clinic input]
3116_asyncio.get_running_loop
3117
3118Return the running event loop. Raise a RuntimeError if there is none.
3119
3120This function is thread-specific.
3121[clinic start generated code]*/
3122
3123static PyObject *
3124_asyncio_get_running_loop_impl(PyObject *module)
3125/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3126{
3127 PyObject *loop;
3128 if (get_running_loop(&loop)) {
3129 return NULL;
3130 }
3131 if (loop == NULL) {
3132 /* There's no currently running event loop */
3133 PyErr_SetString(
3134 PyExc_RuntimeError, "no running event loop");
3135 }
3136 return loop;
3137}
3138
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003139/*[clinic input]
3140_asyncio._register_task
3141
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003142 task: object
3143
3144Register a new task in asyncio as executed by loop.
3145
3146Returns None.
3147[clinic start generated code]*/
3148
3149static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003150_asyncio__register_task_impl(PyObject *module, PyObject *task)
3151/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003152{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003153 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003154 return NULL;
3155 }
3156 Py_RETURN_NONE;
3157}
3158
3159
3160/*[clinic input]
3161_asyncio._unregister_task
3162
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003163 task: object
3164
3165Unregister a task.
3166
3167Returns None.
3168[clinic start generated code]*/
3169
3170static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003171_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3172/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003173{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003174 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003175 return NULL;
3176 }
3177 Py_RETURN_NONE;
3178}
3179
3180
3181/*[clinic input]
3182_asyncio._enter_task
3183
3184 loop: object
3185 task: object
3186
3187Enter into task execution or resume suspended task.
3188
3189Task belongs to loop.
3190
3191Returns None.
3192[clinic start generated code]*/
3193
3194static PyObject *
3195_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3196/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3197{
3198 if (enter_task(loop, task) < 0) {
3199 return NULL;
3200 }
3201 Py_RETURN_NONE;
3202}
3203
3204
3205/*[clinic input]
3206_asyncio._leave_task
3207
3208 loop: object
3209 task: object
3210
3211Leave task execution or suspend a task.
3212
3213Task belongs to loop.
3214
3215Returns None.
3216[clinic start generated code]*/
3217
3218static PyObject *
3219_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3220/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3221{
3222 if (leave_task(loop, task) < 0) {
3223 return NULL;
3224 }
3225 Py_RETURN_NONE;
3226}
3227
Yury Selivanova70232f2017-12-13 14:49:42 -05003228
Yury Selivanov9d411c12018-01-23 15:10:03 -05003229/*********************** PyRunningLoopHolder ********************/
3230
3231
3232static PyRunningLoopHolder *
3233new_running_loop_holder(PyObject *loop)
3234{
3235 PyRunningLoopHolder *rl = PyObject_New(
3236 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3237 if (rl == NULL) {
3238 return NULL;
3239 }
3240
3241#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3242 rl->rl_pid = getpid();
3243#endif
3244
3245 Py_INCREF(loop);
3246 rl->rl_loop = loop;
3247
3248 return rl;
3249}
3250
3251
3252static void
3253PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3254{
3255 Py_CLEAR(rl->rl_loop);
3256 PyObject_Free(rl);
3257}
3258
3259
3260static PyTypeObject PyRunningLoopHolder_Type = {
3261 PyVarObject_HEAD_INIT(NULL, 0)
3262 "_RunningLoopHolder",
3263 sizeof(PyRunningLoopHolder),
3264 .tp_getattro = PyObject_GenericGetAttr,
3265 .tp_flags = Py_TPFLAGS_DEFAULT,
3266 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3267};
3268
3269
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003270/*********************** Module **************************/
3271
3272
3273static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003274module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003275{
3276 PyObject *next;
3277 PyObject *current;
3278
3279 next = (PyObject*) fi_freelist;
3280 while (next != NULL) {
3281 assert(fi_freelist_len > 0);
3282 fi_freelist_len--;
3283
3284 current = next;
3285 next = (PyObject*) ((futureiterobject*) current)->future;
3286 PyObject_GC_Del(current);
3287 }
3288 assert(fi_freelist_len == 0);
3289 fi_freelist = NULL;
3290}
3291
3292
3293static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003294module_free(void *m)
3295{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003296 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003297 Py_CLEAR(traceback_extract_stack);
3298 Py_CLEAR(asyncio_future_repr_info_func);
3299 Py_CLEAR(asyncio_get_event_loop_policy);
3300 Py_CLEAR(asyncio_iscoroutine_func);
3301 Py_CLEAR(asyncio_task_get_stack_func);
3302 Py_CLEAR(asyncio_task_print_stack_func);
3303 Py_CLEAR(asyncio_task_repr_info_func);
3304 Py_CLEAR(asyncio_InvalidStateError);
3305 Py_CLEAR(asyncio_CancelledError);
3306
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003307 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003308 Py_CLEAR(current_tasks);
3309 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003310
Yury Selivanovf23746a2018-01-22 19:11:18 -05003311 Py_CLEAR(context_kwname);
3312
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003313 module_free_freelists();
Jeffrey Quesnellea75e7302020-04-16 22:09:45 -04003314
3315 module_initialized = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003316}
3317
3318static int
3319module_init(void)
3320{
3321 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003322
3323 asyncio_mod = PyImport_ImportModule("asyncio");
3324 if (asyncio_mod == NULL) {
3325 goto fail;
3326 }
Ben Harper321def82019-10-07 12:19:58 -04003327 if (module_initialized != 0) {
3328 return 0;
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02003329 }
Ben Harper321def82019-10-07 12:19:58 -04003330 else {
3331 module_initialized = 1;
3332 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003333
3334 current_tasks = PyDict_New();
3335 if (current_tasks == NULL) {
3336 goto fail;
3337 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003338
Yury Selivanova9d7e552017-12-19 07:18:45 -05003339 iscoroutine_typecache = PySet_New(NULL);
3340 if (iscoroutine_typecache == NULL) {
3341 goto fail;
3342 }
3343
Yury Selivanovf23746a2018-01-22 19:11:18 -05003344
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003345 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003346 if (context_kwname == NULL) {
3347 goto fail;
3348 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003349
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003350#define WITH_MOD(NAME) \
3351 Py_CLEAR(module); \
3352 module = PyImport_ImportModule(NAME); \
3353 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003354 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003355 }
3356
3357#define GET_MOD_ATTR(VAR, NAME) \
3358 VAR = PyObject_GetAttrString(module, NAME); \
3359 if (VAR == NULL) { \
3360 goto fail; \
3361 }
3362
3363 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003364 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003365
3366 WITH_MOD("asyncio.base_futures")
3367 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003368
3369 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003370 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3371 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3372
3373 WITH_MOD("asyncio.base_tasks")
3374 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3375 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3376 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3377
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003378 WITH_MOD("asyncio.coroutines")
3379 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3380
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003381 WITH_MOD("traceback")
3382 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3383
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003384 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003385 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003386 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003387 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003388 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003389 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003390 goto fail;
3391 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003392
Serhiy Storchakabca49392017-09-03 08:10:14 +03003393 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003394 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003395
INADA Naokic411a7d2016-10-18 11:48:14 +09003396fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003397 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003398 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003399 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003400
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003401#undef WITH_MOD
3402#undef GET_MOD_ATTR
3403}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003404
INADA Naokic411a7d2016-10-18 11:48:14 +09003405PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003406
Yury Selivanova70232f2017-12-13 14:49:42 -05003407static PyMethodDef asyncio_methods[] = {
3408 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3409 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3410 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3411 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003412 _ASYNCIO__REGISTER_TASK_METHODDEF
3413 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3414 _ASYNCIO__ENTER_TASK_METHODDEF
3415 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003416 {NULL, NULL}
3417};
3418
INADA Naoki9f2ce252016-10-15 15:39:19 +09003419static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003420 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003421 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003422 module_doc, /* m_doc */
3423 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003424 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003425 NULL, /* m_slots */
3426 NULL, /* m_traverse */
3427 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003428 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003429};
3430
3431
3432PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003433PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003434{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003435 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003436 return NULL;
3437 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003438 if (PyType_Ready(&FutureIterType) < 0) {
3439 return NULL;
3440 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003441 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003442 return NULL;
3443 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003444 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003445 return NULL;
3446 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003447 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3448 return NULL;
3449 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003450
INADA Naoki9f2ce252016-10-15 15:39:19 +09003451 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003452 if (m == NULL) {
3453 return NULL;
3454 }
3455
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003456 /* FutureType and TaskType are made ready by PyModule_AddType() calls below. */
3457 if (PyModule_AddType(m, &FutureType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003458 Py_DECREF(m);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003459 return NULL;
3460 }
3461
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003462 if (PyModule_AddType(m, &TaskType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003463 Py_DECREF(m);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003464 return NULL;
3465 }
3466
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003467 Py_INCREF(all_tasks);
3468 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3469 Py_DECREF(all_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003470 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003471 return NULL;
3472 }
3473
3474 Py_INCREF(current_tasks);
3475 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3476 Py_DECREF(current_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003477 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003478 return NULL;
3479 }
3480
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003481 return m;
3482}