blob: 0608c40f6c3395b2b36a97096233b29410a41592 [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);
Yury Selivanov416c1eb2018-05-28 17:54:02 -040016_Py_IDENTIFIER(_all_tasks_compat);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090017_Py_IDENTIFIER(call_soon);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040018_Py_IDENTIFIER(cancel);
Andrew Svetlov44d1a592017-12-16 21:58:38 +020019_Py_IDENTIFIER(current_task);
Yury Selivanova70232f2017-12-13 14:49:42 -050020_Py_IDENTIFIER(get_event_loop);
Yury Selivanova0c1ba62016-10-28 12:52:37 -040021_Py_IDENTIFIER(send);
22_Py_IDENTIFIER(throw);
INADA Naoki9e4e38e2016-10-09 14:44:47 +090023
24
INADA Naoki9f2ce252016-10-15 15:39:19 +090025/* State of the _asyncio module */
Andrew Svetlov44d1a592017-12-16 21:58:38 +020026static PyObject *asyncio_mod;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020027static PyObject *traceback_extract_stack;
28static PyObject *asyncio_get_event_loop_policy;
29static PyObject *asyncio_future_repr_info_func;
30static PyObject *asyncio_iscoroutine_func;
31static PyObject *asyncio_task_get_stack_func;
32static PyObject *asyncio_task_print_stack_func;
33static PyObject *asyncio_task_repr_info_func;
34static PyObject *asyncio_InvalidStateError;
35static PyObject *asyncio_CancelledError;
Yury Selivanovf23746a2018-01-22 19:11:18 -050036static PyObject *context_kwname;
Ben Harper321def82019-10-07 12:19:58 -040037static int module_initialized;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020038
Yury Selivanov9d411c12018-01-23 15:10:03 -050039static PyObject *cached_running_holder;
40static volatile uint64_t cached_running_holder_tsid;
41
Alex Grönholmcca4eec2018-08-09 00:06:47 +030042/* Counter for autogenerated Task names */
43static uint64_t task_name_counter = 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020044
Yury Selivanovca9b36c2017-12-23 15:04:15 -050045/* WeakSet containing all alive tasks. */
46static PyObject *all_tasks;
Andrew Svetlov44d1a592017-12-16 21:58:38 +020047
48/* Dictionary containing tasks that are currently active in
49 all running event loops. {EventLoop: Task} */
Yury Selivanovca9b36c2017-12-23 15:04:15 -050050static PyObject *current_tasks;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090051
Yury Selivanova9d7e552017-12-19 07:18:45 -050052/* An isinstance type cache for the 'is_coroutine()' function. */
53static PyObject *iscoroutine_typecache;
54
INADA Naoki9e4e38e2016-10-09 14:44:47 +090055
INADA Naoki9e4e38e2016-10-09 14:44:47 +090056typedef enum {
57 STATE_PENDING,
58 STATE_CANCELLED,
59 STATE_FINISHED
60} fut_state;
61
Yury Selivanova0c1ba62016-10-28 12:52:37 -040062#define FutureObj_HEAD(prefix) \
63 PyObject_HEAD \
64 PyObject *prefix##_loop; \
Yury Selivanov1b7c11f2017-12-17 20:19:47 -050065 PyObject *prefix##_callback0; \
Yury Selivanov994269c2018-09-27 14:55:55 -040066 PyObject *prefix##_context0; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040067 PyObject *prefix##_callbacks; \
68 PyObject *prefix##_exception; \
69 PyObject *prefix##_result; \
70 PyObject *prefix##_source_tb; \
Chris Jerdonek1ce58412020-05-15 16:55:50 -070071 PyObject *prefix##_cancel_msg; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -040072 fut_state prefix##_state; \
73 int prefix##_log_tb; \
74 int prefix##_blocking; \
75 PyObject *dict; \
Chris Jerdonekda742ba2020-05-17 22:47:31 -070076 PyObject *prefix##_weakreflist; \
77 _PyErr_StackItem prefix##_cancelled_exc_state;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040078
79typedef struct {
80 FutureObj_HEAD(fut)
81} FutureObj;
82
83typedef struct {
84 FutureObj_HEAD(task)
85 PyObject *task_fut_waiter;
86 PyObject *task_coro;
Alex Grönholmcca4eec2018-08-09 00:06:47 +030087 PyObject *task_name;
Yury Selivanov994269c2018-09-27 14:55:55 -040088 PyObject *task_context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -040089 int task_must_cancel;
90 int task_log_destroy_pending;
91} TaskObj;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090092
93typedef struct {
94 PyObject_HEAD
Yury Selivanova0c1ba62016-10-28 12:52:37 -040095 TaskObj *sw_task;
96 PyObject *sw_arg;
Serhiy Storchakabca49392017-09-03 08:10:14 +030097} TaskStepMethWrapper;
INADA Naoki9e4e38e2016-10-09 14:44:47 +090098
Yury Selivanova0c1ba62016-10-28 12:52:37 -040099typedef struct {
100 PyObject_HEAD
101 TaskObj *ww_task;
102} TaskWakeupMethWrapper;
103
Yury Selivanov9d411c12018-01-23 15:10:03 -0500104typedef struct {
105 PyObject_HEAD
106 PyObject *rl_loop;
107#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
108 pid_t rl_pid;
109#endif
110} PyRunningLoopHolder;
111
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400112
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500113static PyTypeObject FutureType;
114static PyTypeObject TaskType;
Yury Selivanov9d411c12018-01-23 15:10:03 -0500115static PyTypeObject PyRunningLoopHolder_Type;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500116
117
Dong-hee Na1b55b652020-02-17 19:09:15 +0900118#define Future_CheckExact(obj) Py_IS_TYPE(obj, &FutureType)
119#define Task_CheckExact(obj) Py_IS_TYPE(obj, &TaskType)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500120
121#define Future_Check(obj) PyObject_TypeCheck(obj, &FutureType)
122#define Task_Check(obj) PyObject_TypeCheck(obj, &TaskType)
123
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400124#include "clinic/_asynciomodule.c.h"
125
126
127/*[clinic input]
128class _asyncio.Future "FutureObj *" "&Future_Type"
129[clinic start generated code]*/
130/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
131
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500132
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400133/* Get FutureIter from Future */
Yury Selivanov9d411c12018-01-23 15:10:03 -0500134static PyObject * future_new_iter(PyObject *);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900135
Yury Selivanov9d411c12018-01-23 15:10:03 -0500136static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
137
Yury Selivanova70232f2017-12-13 14:49:42 -0500138
139static int
Yury Selivanova9d7e552017-12-19 07:18:45 -0500140_is_coroutine(PyObject *coro)
141{
142 /* 'coro' is not a native coroutine, call asyncio.iscoroutine()
143 to check if it's another coroutine flavour.
144
145 Do this check after 'future_init()'; in case we need to raise
146 an error, __del__ needs a properly initialized object.
147 */
Petr Viktorinffd97532020-02-11 17:46:57 +0100148 PyObject *res = PyObject_CallOneArg(asyncio_iscoroutine_func, coro);
Yury Selivanova9d7e552017-12-19 07:18:45 -0500149 if (res == NULL) {
150 return -1;
151 }
152
153 int is_res_true = PyObject_IsTrue(res);
154 Py_DECREF(res);
155 if (is_res_true <= 0) {
156 return is_res_true;
157 }
158
Andrew Svetlov0f47fa22017-12-23 22:06:46 +0200159 if (PySet_GET_SIZE(iscoroutine_typecache) < 100) {
Yury Selivanova9d7e552017-12-19 07:18:45 -0500160 /* Just in case we don't want to cache more than 100
161 positive types. That shouldn't ever happen, unless
162 someone stressing the system on purpose.
163 */
164 if (PySet_Add(iscoroutine_typecache, (PyObject*) Py_TYPE(coro))) {
165 return -1;
166 }
167 }
168
169 return 1;
170}
171
172
173static inline int
174is_coroutine(PyObject *coro)
175{
176 if (PyCoro_CheckExact(coro)) {
177 return 1;
178 }
179
180 /* Check if `type(coro)` is in the cache.
181 Caching makes is_coroutine() function almost as fast as
182 PyCoro_CheckExact() for non-native coroutine-like objects
183 (like coroutines compiled with Cython).
184
185 asyncio.iscoroutine() has its own type caching mechanism.
186 This cache allows us to avoid the cost of even calling
187 a pure-Python function in 99.9% cases.
188 */
189 int has_it = PySet_Contains(
190 iscoroutine_typecache, (PyObject*) Py_TYPE(coro));
191 if (has_it == 0) {
192 /* type(coro) is not in iscoroutine_typecache */
193 return _is_coroutine(coro);
194 }
195
Leo Ariasc3d95082018-02-03 18:36:10 -0600196 /* either an error has occurred or
Yury Selivanova9d7e552017-12-19 07:18:45 -0500197 type(coro) is in iscoroutine_typecache
198 */
199 return has_it;
200}
201
202
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500203static PyObject *
204get_future_loop(PyObject *fut)
205{
206 /* Implementation of `asyncio.futures._get_loop` */
207
208 _Py_IDENTIFIER(get_loop);
209 _Py_IDENTIFIER(_loop);
Serhiy Storchaka66553542018-05-20 16:30:31 +0300210 PyObject *getloop;
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500211
212 if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
213 PyObject *loop = ((FutureObj *)fut)->fut_loop;
214 Py_INCREF(loop);
215 return loop;
216 }
217
Serhiy Storchaka66553542018-05-20 16:30:31 +0300218 if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) {
219 return NULL;
220 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500221 if (getloop != NULL) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200222 PyObject *res = PyObject_CallNoArgs(getloop);
Yury Selivanovca9b36c2017-12-23 15:04:15 -0500223 Py_DECREF(getloop);
224 return res;
225 }
226
227 return _PyObject_GetAttrId(fut, &PyId__loop);
228}
229
230
Yury Selivanova9d7e552017-12-19 07:18:45 -0500231static int
Yury Selivanova70232f2017-12-13 14:49:42 -0500232get_running_loop(PyObject **loop)
233{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500234 PyObject *rl;
Yury Selivanova70232f2017-12-13 14:49:42 -0500235
Yury Selivanov9d411c12018-01-23 15:10:03 -0500236 PyThreadState *ts = PyThreadState_Get();
Victor Stinner5c3cda02020-03-25 21:23:53 +0100237 uint64_t ts_id = PyThreadState_GetID(ts);
238 if (ts_id == cached_running_holder_tsid && cached_running_holder != NULL) {
Yury Selivanov9d411c12018-01-23 15:10:03 -0500239 // Fast path, check the cache.
240 rl = cached_running_holder; // borrowed
241 }
242 else {
Victor Stinner0e427c62020-03-25 21:22:55 +0100243 PyObject *ts_dict = _PyThreadState_GetDict(ts); // borrowed
244 if (ts_dict == NULL) {
Yury Selivanov9d411c12018-01-23 15:10:03 -0500245 goto not_found;
246 }
247
248 rl = _PyDict_GetItemIdWithError(
Victor Stinner0e427c62020-03-25 21:22:55 +0100249 ts_dict, &PyId___asyncio_running_event_loop__); // borrowed
Yury Selivanov9d411c12018-01-23 15:10:03 -0500250 if (rl == NULL) {
251 if (PyErr_Occurred()) {
252 goto error;
253 }
254 else {
255 goto not_found;
256 }
257 }
258
259 cached_running_holder = rl; // borrowed
Victor Stinner5c3cda02020-03-25 21:23:53 +0100260 cached_running_holder_tsid = ts_id;
Yury Selivanova70232f2017-12-13 14:49:42 -0500261 }
262
Dong-hee Na1b55b652020-02-17 19:09:15 +0900263 assert(Py_IS_TYPE(rl, &PyRunningLoopHolder_Type));
Yury Selivanov9d411c12018-01-23 15:10:03 -0500264 PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
Yury Selivanova70232f2017-12-13 14:49:42 -0500265
266 if (running_loop == Py_None) {
267 goto not_found;
268 }
269
Yury Selivanov9d411c12018-01-23 15:10:03 -0500270#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
271 /* On Windows there is no getpid, but there is also no os.fork(),
272 so there is no need for this check.
273 */
274 if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
275 goto not_found;
Yury Selivanova70232f2017-12-13 14:49:42 -0500276 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500277#endif
Yury Selivanova70232f2017-12-13 14:49:42 -0500278
Yury Selivanov9d411c12018-01-23 15:10:03 -0500279 Py_INCREF(running_loop);
280 *loop = running_loop;
281 return 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500282
283not_found:
284 *loop = NULL;
285 return 0;
286
Yury Selivanova70232f2017-12-13 14:49:42 -0500287error:
288 *loop = NULL;
289 return -1;
290}
291
292
293static int
294set_running_loop(PyObject *loop)
295{
Yury Selivanov9d411c12018-01-23 15:10:03 -0500296 cached_running_holder = NULL;
297 cached_running_holder_tsid = 0;
Yury Selivanova70232f2017-12-13 14:49:42 -0500298
Yury Selivanov9d411c12018-01-23 15:10:03 -0500299 PyObject *ts_dict = PyThreadState_GetDict(); // borrowed
Yury Selivanova70232f2017-12-13 14:49:42 -0500300 if (ts_dict == NULL) {
301 PyErr_SetString(
302 PyExc_RuntimeError, "thread-local storage is not available");
303 return -1;
304 }
305
Yury Selivanov9d411c12018-01-23 15:10:03 -0500306 PyRunningLoopHolder *rl = new_running_loop_holder(loop);
307 if (rl == NULL) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500308 return -1;
309 }
310
Yury Selivanova70232f2017-12-13 14:49:42 -0500311 if (_PyDict_SetItemId(
Yury Selivanov9d411c12018-01-23 15:10:03 -0500312 ts_dict, &PyId___asyncio_running_event_loop__, (PyObject *)rl) < 0)
313 {
314 Py_DECREF(rl); // will cleanup loop & current_pid
Yury Selivanova70232f2017-12-13 14:49:42 -0500315 return -1;
316 }
Yury Selivanov9d411c12018-01-23 15:10:03 -0500317 Py_DECREF(rl);
Yury Selivanova70232f2017-12-13 14:49:42 -0500318
319 return 0;
320}
321
322
323static PyObject *
324get_event_loop(void)
325{
326 PyObject *loop;
327 PyObject *policy;
328
329 if (get_running_loop(&loop)) {
330 return NULL;
331 }
332 if (loop != NULL) {
333 return loop;
334 }
335
Victor Stinner2ff58a22019-06-17 14:27:23 +0200336 policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy);
Yury Selivanova70232f2017-12-13 14:49:42 -0500337 if (policy == NULL) {
338 return NULL;
339 }
340
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200341 loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
Yury Selivanova70232f2017-12-13 14:49:42 -0500342 Py_DECREF(policy);
343 return loop;
344}
345
346
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900347static int
Yury Selivanov994269c2018-09-27 14:55:55 -0400348call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500349{
350 PyObject *handle;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500351 PyObject *stack[3];
352 Py_ssize_t nargs;
353
354 if (ctx == NULL) {
355 handle = _PyObject_CallMethodIdObjArgs(
356 loop, &PyId_call_soon, func, arg, NULL);
357 }
358 else {
359 /* Use FASTCALL to pass a keyword-only argument to call_soon */
360
361 PyObject *callable = _PyObject_GetAttrId(loop, &PyId_call_soon);
362 if (callable == NULL) {
363 return -1;
364 }
365
366 /* All refs in 'stack' are borrowed. */
367 nargs = 1;
368 stack[0] = func;
369 if (arg != NULL) {
370 stack[1] = arg;
371 nargs++;
372 }
373 stack[nargs] = (PyObject *)ctx;
374
Petr Viktorinffd97532020-02-11 17:46:57 +0100375 handle = PyObject_Vectorcall(callable, stack, nargs, context_kwname);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500376 Py_DECREF(callable);
377 }
378
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500379 if (handle == NULL) {
380 return -1;
381 }
382 Py_DECREF(handle);
383 return 0;
384}
385
386
387static inline int
388future_is_alive(FutureObj *fut)
389{
390 return fut->fut_loop != NULL;
391}
392
393
394static inline int
395future_ensure_alive(FutureObj *fut)
396{
397 if (!future_is_alive(fut)) {
398 PyErr_SetString(PyExc_RuntimeError,
399 "Future object is not initialized.");
400 return -1;
401 }
402 return 0;
403}
404
405
406#define ENSURE_FUTURE_ALIVE(fut) \
407 do { \
408 assert(Future_Check(fut) || Task_Check(fut)); \
409 if (future_ensure_alive((FutureObj*)fut)) { \
410 return NULL; \
411 } \
412 } while(0);
413
414
415static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400416future_schedule_callbacks(FutureObj *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900417{
418 Py_ssize_t len;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500419 Py_ssize_t i;
420
421 if (fut->fut_callback0 != NULL) {
422 /* There's a 1st callback */
423
424 int ret = call_soon(
Yury Selivanovf23746a2018-01-22 19:11:18 -0500425 fut->fut_loop, fut->fut_callback0,
426 (PyObject *)fut, fut->fut_context0);
427
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500428 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500429 Py_CLEAR(fut->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500430 if (ret) {
431 /* If an error occurs in pure-Python implementation,
432 all callbacks are cleared. */
433 Py_CLEAR(fut->fut_callbacks);
434 return ret;
435 }
436
437 /* we called the first callback, now try calling
438 callbacks from the 'fut_callbacks' list. */
439 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900440
441 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500442 /* No more callbacks, return. */
443 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900444 }
445
446 len = PyList_GET_SIZE(fut->fut_callbacks);
447 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500448 /* The list of callbacks was empty; clear it and return. */
449 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900450 return 0;
451 }
452
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900453 for (i = 0; i < len; i++) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500454 PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
455 PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
456 PyObject *ctx = PyTuple_GET_ITEM(cb_tup, 1);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900457
Yury Selivanov994269c2018-09-27 14:55:55 -0400458 if (call_soon(fut->fut_loop, cb, (PyObject *)fut, ctx)) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500459 /* If an error occurs in pure-Python implementation,
460 all callbacks are cleared. */
461 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900462 return -1;
463 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900464 }
465
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500466 Py_CLEAR(fut->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900467 return 0;
468}
469
Oren Milmand019bc82018-02-13 12:28:33 +0200470
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900471static int
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400472future_init(FutureObj *fut, PyObject *loop)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900473{
Serhiy Storchakabca49392017-09-03 08:10:14 +0300474 PyObject *res;
475 int is_true;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900476 _Py_IDENTIFIER(get_debug);
477
Oren Milmand019bc82018-02-13 12:28:33 +0200478 // Same to FutureObj_clear() but not clearing fut->dict
479 Py_CLEAR(fut->fut_loop);
480 Py_CLEAR(fut->fut_callback0);
481 Py_CLEAR(fut->fut_context0);
482 Py_CLEAR(fut->fut_callbacks);
483 Py_CLEAR(fut->fut_result);
484 Py_CLEAR(fut->fut_exception);
485 Py_CLEAR(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700486 Py_CLEAR(fut->fut_cancel_msg);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700487 _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
Oren Milmand019bc82018-02-13 12:28:33 +0200488
489 fut->fut_state = STATE_PENDING;
490 fut->fut_log_tb = 0;
491 fut->fut_blocking = 0;
492
Serhiy Storchakabca49392017-09-03 08:10:14 +0300493 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -0500494 loop = get_event_loop();
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900495 if (loop == NULL) {
496 return -1;
497 }
498 }
499 else {
500 Py_INCREF(loop);
501 }
Oren Milmand019bc82018-02-13 12:28:33 +0200502 fut->fut_loop = loop;
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900503
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200504 res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900505 if (res == NULL) {
506 return -1;
507 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300508 is_true = PyObject_IsTrue(res);
509 Py_DECREF(res);
510 if (is_true < 0) {
511 return -1;
512 }
Yury Selivanov35230d02018-05-28 11:11:31 -0400513 if (is_true && !_Py_IsFinalizing()) {
514 /* Only try to capture the traceback if the interpreter is not being
515 finalized. The original motivation to add a `_Py_IsFinalizing()`
516 call was to prevent SIGSEGV when a Future is created in a __del__
517 method, which is called during the interpreter shutdown and the
518 traceback module is already unloaded.
519 */
Victor Stinner2ff58a22019-06-17 14:27:23 +0200520 fut->fut_source_tb = PyObject_CallNoArgs(traceback_extract_stack);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900521 if (fut->fut_source_tb == NULL) {
522 return -1;
523 }
524 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900525
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900526 return 0;
527}
528
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900529static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400530future_set_result(FutureObj *fut, PyObject *res)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900531{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500532 if (future_ensure_alive(fut)) {
533 return NULL;
534 }
535
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900536 if (fut->fut_state != STATE_PENDING) {
537 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
538 return NULL;
539 }
540
Serhiy Storchakabca49392017-09-03 08:10:14 +0300541 assert(!fut->fut_result);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900542 Py_INCREF(res);
543 fut->fut_result = res;
544 fut->fut_state = STATE_FINISHED;
545
Yury Selivanov22feeb82018-01-24 11:31:01 -0500546 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900547 return NULL;
548 }
549 Py_RETURN_NONE;
550}
551
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900552static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400553future_set_exception(FutureObj *fut, PyObject *exc)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900554{
555 PyObject *exc_val = NULL;
556
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900557 if (fut->fut_state != STATE_PENDING) {
558 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
559 return NULL;
560 }
561
562 if (PyExceptionClass_Check(exc)) {
Victor Stinner2ff58a22019-06-17 14:27:23 +0200563 exc_val = PyObject_CallNoArgs(exc);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900564 if (exc_val == NULL) {
565 return NULL;
566 }
Serhiy Storchakabca49392017-09-03 08:10:14 +0300567 if (fut->fut_state != STATE_PENDING) {
568 Py_DECREF(exc_val);
569 PyErr_SetString(asyncio_InvalidStateError, "invalid state");
570 return NULL;
571 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900572 }
573 else {
574 exc_val = exc;
575 Py_INCREF(exc_val);
576 }
577 if (!PyExceptionInstance_Check(exc_val)) {
578 Py_DECREF(exc_val);
579 PyErr_SetString(PyExc_TypeError, "invalid exception object");
580 return NULL;
581 }
Andy Lesterdffe4c02020-03-04 07:15:20 -0600582 if (Py_IS_TYPE(exc_val, (PyTypeObject *)PyExc_StopIteration)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900583 Py_DECREF(exc_val);
584 PyErr_SetString(PyExc_TypeError,
585 "StopIteration interacts badly with generators "
586 "and cannot be raised into a Future");
587 return NULL;
588 }
589
Serhiy Storchakabca49392017-09-03 08:10:14 +0300590 assert(!fut->fut_exception);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900591 fut->fut_exception = exc_val;
592 fut->fut_state = STATE_FINISHED;
593
Yury Selivanov22feeb82018-01-24 11:31:01 -0500594 if (future_schedule_callbacks(fut) == -1) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900595 return NULL;
596 }
597
598 fut->fut_log_tb = 1;
599 Py_RETURN_NONE;
600}
601
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700602static PyObject *
603create_cancelled_error(PyObject *msg)
604{
605 PyObject *exc;
606 if (msg == NULL || msg == Py_None) {
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700607 exc = PyObject_CallNoArgs(asyncio_CancelledError);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700608 } else {
609 exc = PyObject_CallOneArg(asyncio_CancelledError, msg);
610 }
611 return exc;
612}
613
614static void
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700615future_set_cancelled_error(FutureObj *fut)
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700616{
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700617 PyObject *exc = create_cancelled_error(fut->fut_cancel_msg);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700618 PyErr_SetObject(asyncio_CancelledError, exc);
619 Py_DECREF(exc);
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700620
621 _PyErr_ChainStackItem(&fut->fut_cancelled_exc_state);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700622}
623
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400624static int
625future_get_result(FutureObj *fut, PyObject **result)
626{
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400627 if (fut->fut_state == STATE_CANCELLED) {
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700628 future_set_cancelled_error(fut);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300629 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400630 }
631
632 if (fut->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300633 PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
634 return -1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400635 }
636
637 fut->fut_log_tb = 0;
638 if (fut->fut_exception != NULL) {
639 Py_INCREF(fut->fut_exception);
640 *result = fut->fut_exception;
641 return 1;
642 }
643
644 Py_INCREF(fut->fut_result);
645 *result = fut->fut_result;
646 return 0;
647}
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900648
649static PyObject *
Yury Selivanov994269c2018-09-27 14:55:55 -0400650future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx)
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900651{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500652 if (!future_is_alive(fut)) {
653 PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
654 return NULL;
655 }
656
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900657 if (fut->fut_state != STATE_PENDING) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500658 /* The future is done/cancelled, so schedule the callback
659 right away. */
Yury Selivanovf23746a2018-01-22 19:11:18 -0500660 if (call_soon(fut->fut_loop, arg, (PyObject*) fut, ctx)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900661 return NULL;
662 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900663 }
664 else {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500665 /* The future is pending, add a callback.
666
667 Callbacks in the future object are stored as follows:
668
669 callback0 -- a pointer to the first callback
670 callbacks -- a list of 2nd, 3rd, ... callbacks
671
672 Invariants:
673
674 * callbacks != NULL:
675 There are some callbacks in in the list. Just
676 add the new callback to it.
677
678 * callbacks == NULL and callback0 == NULL:
679 This is the first callback. Set it to callback0.
680
681 * callbacks == NULL and callback0 != NULL:
682 This is a second callback. Initialize callbacks
683 with a new list and add the new callback to it.
684 */
685
Yury Selivanovf23746a2018-01-22 19:11:18 -0500686 if (fut->fut_callbacks == NULL && fut->fut_callback0 == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500687 Py_INCREF(arg);
688 fut->fut_callback0 = arg;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500689 Py_INCREF(ctx);
690 fut->fut_context0 = ctx;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500691 }
692 else {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500693 PyObject *tup = PyTuple_New(2);
694 if (tup == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500695 return NULL;
696 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500697 Py_INCREF(arg);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500698 PyTuple_SET_ITEM(tup, 0, arg);
699 Py_INCREF(ctx);
700 PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx);
701
702 if (fut->fut_callbacks != NULL) {
703 int err = PyList_Append(fut->fut_callbacks, tup);
704 if (err) {
705 Py_DECREF(tup);
706 return NULL;
707 }
708 Py_DECREF(tup);
709 }
710 else {
711 fut->fut_callbacks = PyList_New(1);
712 if (fut->fut_callbacks == NULL) {
713 return NULL;
714 }
715
716 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
717 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900718 }
719 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500720
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900721 Py_RETURN_NONE;
722}
723
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400724static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700725future_cancel(FutureObj *fut, PyObject *msg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400726{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000727 fut->fut_log_tb = 0;
728
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400729 if (fut->fut_state != STATE_PENDING) {
730 Py_RETURN_FALSE;
731 }
732 fut->fut_state = STATE_CANCELLED;
733
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700734 Py_XINCREF(msg);
735 Py_XSETREF(fut->fut_cancel_msg, msg);
736
Yury Selivanov22feeb82018-01-24 11:31:01 -0500737 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400738 return NULL;
739 }
740
741 Py_RETURN_TRUE;
742}
743
744/*[clinic input]
745_asyncio.Future.__init__
746
747 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300748 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400749
750This class is *almost* compatible with concurrent.futures.Future.
751
752 Differences:
753
754 - result() and exception() do not take a timeout argument and
755 raise an exception when the future isn't done yet.
756
757 - Callbacks registered with add_done_callback() are always called
758 via the event loop's call_soon_threadsafe().
759
760 - This class is not compatible with the wait() and as_completed()
761 methods in the concurrent.futures package.
762[clinic start generated code]*/
763
764static int
765_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300766/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400767
768{
769 return future_init(self, loop);
770}
771
772static int
773FutureObj_clear(FutureObj *fut)
774{
775 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500776 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500777 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400778 Py_CLEAR(fut->fut_callbacks);
779 Py_CLEAR(fut->fut_result);
780 Py_CLEAR(fut->fut_exception);
781 Py_CLEAR(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700782 Py_CLEAR(fut->fut_cancel_msg);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700783 _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400784 Py_CLEAR(fut->dict);
785 return 0;
786}
787
788static int
789FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
790{
791 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500792 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500793 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400794 Py_VISIT(fut->fut_callbacks);
795 Py_VISIT(fut->fut_result);
796 Py_VISIT(fut->fut_exception);
797 Py_VISIT(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700798 Py_VISIT(fut->fut_cancel_msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400799 Py_VISIT(fut->dict);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700800
801 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
802 Py_VISIT(exc_state->exc_type);
803 Py_VISIT(exc_state->exc_value);
804 Py_VISIT(exc_state->exc_traceback);
805
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400806 return 0;
807}
808
809/*[clinic input]
810_asyncio.Future.result
811
812Return the result this future represents.
813
814If the future has been cancelled, raises CancelledError. If the
815future's result isn't yet available, raises InvalidStateError. If
816the future is done and has an exception set, this exception is raised.
817[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900818
819static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400820_asyncio_Future_result_impl(FutureObj *self)
821/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
822{
823 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500824
825 if (!future_is_alive(self)) {
826 PyErr_SetString(asyncio_InvalidStateError,
827 "Future object is not initialized.");
828 return NULL;
829 }
830
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400831 int res = future_get_result(self, &result);
832
833 if (res == -1) {
834 return NULL;
835 }
836
837 if (res == 0) {
838 return result;
839 }
840
841 assert(res == 1);
842
843 PyErr_SetObject(PyExceptionInstance_Class(result), result);
844 Py_DECREF(result);
845 return NULL;
846}
847
848/*[clinic input]
849_asyncio.Future.exception
850
851Return the exception that was set on this future.
852
853The exception (or None if no exception was set) is returned only if
854the future is done. If the future has been cancelled, raises
855CancelledError. If the future isn't done yet, raises
856InvalidStateError.
857[clinic start generated code]*/
858
859static PyObject *
860_asyncio_Future_exception_impl(FutureObj *self)
861/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
862{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500863 if (!future_is_alive(self)) {
864 PyErr_SetString(asyncio_InvalidStateError,
865 "Future object is not initialized.");
866 return NULL;
867 }
868
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400869 if (self->fut_state == STATE_CANCELLED) {
Miss Islington (bot)7f77ac42020-05-22 14:35:22 -0700870 future_set_cancelled_error(self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400871 return NULL;
872 }
873
874 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300875 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400876 return NULL;
877 }
878
879 if (self->fut_exception != NULL) {
880 self->fut_log_tb = 0;
881 Py_INCREF(self->fut_exception);
882 return self->fut_exception;
883 }
884
885 Py_RETURN_NONE;
886}
887
888/*[clinic input]
889_asyncio.Future.set_result
890
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500891 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400892 /
893
894Mark the future done and set its result.
895
896If the future is already done when this method is called, raises
897InvalidStateError.
898[clinic start generated code]*/
899
900static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500901_asyncio_Future_set_result(FutureObj *self, PyObject *result)
902/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400903{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500904 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500905 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400906}
907
908/*[clinic input]
909_asyncio.Future.set_exception
910
Serhiy Storchakabca49392017-09-03 08:10:14 +0300911 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400912 /
913
914Mark the future done and set an exception.
915
916If the future is already done when this method is called, raises
917InvalidStateError.
918[clinic start generated code]*/
919
920static PyObject *
921_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300922/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400923{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500924 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400925 return future_set_exception(self, exception);
926}
927
928/*[clinic input]
929_asyncio.Future.add_done_callback
930
Serhiy Storchakabca49392017-09-03 08:10:14 +0300931 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400932 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500933 *
934 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400935
936Add a callback to be run when the future becomes done.
937
938The callback is called with a single argument - the future object. If
939the future is already done when this is called, the callback is
940scheduled with call_soon.
941[clinic start generated code]*/
942
943static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500944_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
945 PyObject *context)
946/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400947{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500948 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400949 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500950 if (context == NULL) {
951 return NULL;
952 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400953 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500954 Py_DECREF(context);
955 return res;
956 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400957 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400958}
959
960/*[clinic input]
961_asyncio.Future.remove_done_callback
962
Serhiy Storchakabca49392017-09-03 08:10:14 +0300963 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400964 /
965
966Remove all instances of a callback from the "call when done" list.
967
968Returns the number of callbacks removed.
969[clinic start generated code]*/
970
971static PyObject *
972_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300973/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900974{
975 PyObject *newlist;
976 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500977 Py_ssize_t cleared_callback0 = 0;
978
979 ENSURE_FUTURE_ALIVE(self)
980
981 if (self->fut_callback0 != NULL) {
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300982 int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500983 if (cmp == -1) {
984 return NULL;
985 }
986 if (cmp == 1) {
987 /* callback0 == fn */
988 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500989 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500990 cleared_callback0 = 1;
991 }
992 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900993
Serhiy Storchakabca49392017-09-03 08:10:14 +0300994 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500995 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300996 }
997
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400998 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900999 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001000 Py_CLEAR(self->fut_callbacks);
1001 return PyLong_FromSsize_t(cleared_callback0);
1002 }
1003
1004 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -05001005 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001006 int cmp = PyObject_RichCompareBool(
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001007 PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001008 if (cmp == -1) {
1009 return NULL;
1010 }
1011 if (cmp == 1) {
1012 /* callbacks[0] == fn */
1013 Py_CLEAR(self->fut_callbacks);
1014 return PyLong_FromSsize_t(1 + cleared_callback0);
1015 }
1016 /* callbacks[0] != fn and len(callbacks) == 1 */
1017 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001018 }
1019
1020 newlist = PyList_New(len);
1021 if (newlist == NULL) {
1022 return NULL;
1023 }
1024
Yury Selivanov84af9032017-03-02 23:46:56 -05001025 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001026 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001027 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001028 Py_INCREF(item);
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001029 ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001030 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001031 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001032 PyList_SET_ITEM(newlist, j, item);
1033 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001034 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -04001035 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001036 ret = PyList_Append(newlist, item);
1037 }
1038 Py_DECREF(item);
1039 if (ret < 0) {
1040 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001041 }
1042 }
1043
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001044 if (j == 0) {
1045 Py_CLEAR(self->fut_callbacks);
1046 Py_DECREF(newlist);
1047 return PyLong_FromSsize_t(len + cleared_callback0);
1048 }
1049
Serhiy Storchakabca49392017-09-03 08:10:14 +03001050 if (j < len) {
Victor Stinner60ac6ed2020-02-07 23:18:08 +01001051 Py_SET_SIZE(newlist, j);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001052 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001053 j = PyList_GET_SIZE(newlist);
1054 len = PyList_GET_SIZE(self->fut_callbacks);
1055 if (j != len) {
1056 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1057 goto fail;
1058 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001059 }
1060 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001061 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001062
1063fail:
1064 Py_DECREF(newlist);
1065 return NULL;
1066}
1067
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001068/*[clinic input]
1069_asyncio.Future.cancel
1070
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001071 msg: object = None
1072
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001073Cancel the future and schedule callbacks.
1074
1075If the future is already done or cancelled, return False. Otherwise,
1076change the future's state to cancelled, schedule the callbacks and
1077return True.
1078[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001079
1080static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001081_asyncio_Future_cancel_impl(FutureObj *self, PyObject *msg)
1082/*[clinic end generated code: output=3edebbc668e5aba3 input=925eb545251f2c5a]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001083{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001084 ENSURE_FUTURE_ALIVE(self)
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001085 return future_cancel(self, msg);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001086}
1087
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001088/*[clinic input]
1089_asyncio.Future.cancelled
1090
1091Return True if the future was cancelled.
1092[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001093
1094static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001095_asyncio_Future_cancelled_impl(FutureObj *self)
1096/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001097{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001098 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001099 Py_RETURN_TRUE;
1100 }
1101 else {
1102 Py_RETURN_FALSE;
1103 }
1104}
1105
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001106/*[clinic input]
1107_asyncio.Future.done
1108
1109Return True if the future is done.
1110
1111Done means either that a result / exception are available, or that the
1112future was cancelled.
1113[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001114
1115static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001116_asyncio_Future_done_impl(FutureObj *self)
1117/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001118{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001119 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001120 Py_RETURN_FALSE;
1121 }
1122 else {
1123 Py_RETURN_TRUE;
1124 }
1125}
1126
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001127/*[clinic input]
1128_asyncio.Future.get_loop
1129
1130Return the event loop the Future is bound to.
1131[clinic start generated code]*/
1132
1133static PyObject *
1134_asyncio_Future_get_loop_impl(FutureObj *self)
1135/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1136{
Andrew Svetlovdad6be52019-11-13 23:36:46 +02001137 ENSURE_FUTURE_ALIVE(self)
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001138 Py_INCREF(self->fut_loop);
1139 return self->fut_loop;
1140}
1141
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001142static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001143FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001144{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001145 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001146 Py_RETURN_TRUE;
1147 }
1148 else {
1149 Py_RETURN_FALSE;
1150 }
1151}
1152
1153static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001154FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001155{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001156 if (future_ensure_alive(fut)) {
1157 return -1;
1158 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001159 if (val == NULL) {
1160 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1161 return -1;
1162 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001163
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001164 int is_true = PyObject_IsTrue(val);
1165 if (is_true < 0) {
1166 return -1;
1167 }
1168 fut->fut_blocking = is_true;
1169 return 0;
1170}
1171
1172static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001173FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001174{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001175 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001176 if (fut->fut_log_tb) {
1177 Py_RETURN_TRUE;
1178 }
1179 else {
1180 Py_RETURN_FALSE;
1181 }
1182}
1183
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001184static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001185FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001186{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001187 if (val == NULL) {
1188 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1189 return -1;
1190 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001191 int is_true = PyObject_IsTrue(val);
1192 if (is_true < 0) {
1193 return -1;
1194 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001195 if (is_true) {
1196 PyErr_SetString(PyExc_ValueError,
1197 "_log_traceback can only be set to False");
1198 return -1;
1199 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001200 fut->fut_log_tb = is_true;
1201 return 0;
1202}
1203
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001204static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001205FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001206{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001207 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001208 Py_RETURN_NONE;
1209 }
1210 Py_INCREF(fut->fut_loop);
1211 return fut->fut_loop;
1212}
1213
1214static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001215FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001216{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001217 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001218
1219 ENSURE_FUTURE_ALIVE(fut)
1220
Yury Selivanovf23746a2018-01-22 19:11:18 -05001221 if (fut->fut_callback0 == NULL) {
1222 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001223 Py_RETURN_NONE;
1224 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001225
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001226 Py_INCREF(fut->fut_callbacks);
1227 return fut->fut_callbacks;
1228 }
1229
Yury Selivanovf23746a2018-01-22 19:11:18 -05001230 Py_ssize_t len = 1;
1231 if (fut->fut_callbacks != NULL) {
1232 len += PyList_GET_SIZE(fut->fut_callbacks);
1233 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001234
Yury Selivanovf23746a2018-01-22 19:11:18 -05001235
1236 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001237 if (new_list == NULL) {
1238 return NULL;
1239 }
1240
Yury Selivanovf23746a2018-01-22 19:11:18 -05001241 PyObject *tup0 = PyTuple_New(2);
1242 if (tup0 == NULL) {
1243 Py_DECREF(new_list);
1244 return NULL;
1245 }
1246
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001247 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001248 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1249 assert(fut->fut_context0 != NULL);
1250 Py_INCREF(fut->fut_context0);
1251 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1252
1253 PyList_SET_ITEM(new_list, 0, tup0);
1254
1255 if (fut->fut_callbacks != NULL) {
1256 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1257 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1258 Py_INCREF(cb);
1259 PyList_SET_ITEM(new_list, i + 1, cb);
1260 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001261 }
1262
1263 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001264}
1265
1266static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001267FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001268{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001269 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001270 if (fut->fut_result == NULL) {
1271 Py_RETURN_NONE;
1272 }
1273 Py_INCREF(fut->fut_result);
1274 return fut->fut_result;
1275}
1276
1277static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001278FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001279{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001280 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001281 if (fut->fut_exception == NULL) {
1282 Py_RETURN_NONE;
1283 }
1284 Py_INCREF(fut->fut_exception);
1285 return fut->fut_exception;
1286}
1287
1288static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001289FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001290{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001291 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001292 Py_RETURN_NONE;
1293 }
1294 Py_INCREF(fut->fut_source_tb);
1295 return fut->fut_source_tb;
1296}
1297
1298static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001299FutureObj_get_cancel_message(FutureObj *fut, void *Py_UNUSED(ignored))
1300{
1301 if (fut->fut_cancel_msg == NULL) {
1302 Py_RETURN_NONE;
1303 }
1304 Py_INCREF(fut->fut_cancel_msg);
1305 return fut->fut_cancel_msg;
1306}
1307
1308static int
1309FutureObj_set_cancel_message(FutureObj *fut, PyObject *msg,
1310 void *Py_UNUSED(ignored))
1311{
1312 if (msg == NULL) {
1313 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1314 return -1;
1315 }
1316 Py_INCREF(msg);
1317 Py_XSETREF(fut->fut_cancel_msg, msg);
1318 return 0;
1319}
1320
1321static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001322FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001323{
1324 _Py_IDENTIFIER(PENDING);
1325 _Py_IDENTIFIER(CANCELLED);
1326 _Py_IDENTIFIER(FINISHED);
1327 PyObject *ret = NULL;
1328
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001329 ENSURE_FUTURE_ALIVE(fut)
1330
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001331 switch (fut->fut_state) {
1332 case STATE_PENDING:
1333 ret = _PyUnicode_FromId(&PyId_PENDING);
1334 break;
1335 case STATE_CANCELLED:
1336 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1337 break;
1338 case STATE_FINISHED:
1339 ret = _PyUnicode_FromId(&PyId_FINISHED);
1340 break;
1341 default:
1342 assert (0);
1343 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001344 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001345 return ret;
1346}
1347
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001348/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001349_asyncio.Future._make_cancelled_error
1350
1351Create the CancelledError to raise if the Future is cancelled.
1352
1353This should only be called once when handling a cancellation since
1354it erases the context exception value.
1355[clinic start generated code]*/
1356
1357static PyObject *
1358_asyncio_Future__make_cancelled_error_impl(FutureObj *self)
1359/*[clinic end generated code: output=a5df276f6c1213de input=ac6effe4ba795ecc]*/
1360{
1361 PyObject *exc = create_cancelled_error(self->fut_cancel_msg);
1362 _PyErr_StackItem *exc_state = &self->fut_cancelled_exc_state;
1363 /* Transfer ownership of exc_value from exc_state to exc since we are
1364 done with it. */
1365 PyException_SetContext(exc, exc_state->exc_value);
1366 exc_state->exc_value = NULL;
1367
1368 return exc;
1369}
1370
1371/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001372_asyncio.Future._repr_info
1373[clinic start generated code]*/
1374
1375static PyObject *
1376_asyncio_Future__repr_info_impl(FutureObj *self)
1377/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001378{
Petr Viktorinffd97532020-02-11 17:46:57 +01001379 return PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001380}
1381
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001382static PyObject *
1383FutureObj_repr(FutureObj *fut)
1384{
1385 _Py_IDENTIFIER(_repr_info);
1386
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001387 ENSURE_FUTURE_ALIVE(fut)
1388
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001389 PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
1390 &PyId__repr_info);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001391 if (rinfo == NULL) {
1392 return NULL;
1393 }
1394
Serhiy Storchakabca49392017-09-03 08:10:14 +03001395 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001396 Py_DECREF(rinfo);
1397 if (rinfo_s == NULL) {
1398 return NULL;
1399 }
1400
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001401 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1402 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001403 Py_DECREF(rinfo_s);
1404 return rstr;
1405}
1406
1407static void
1408FutureObj_finalize(FutureObj *fut)
1409{
1410 _Py_IDENTIFIER(call_exception_handler);
1411 _Py_IDENTIFIER(message);
1412 _Py_IDENTIFIER(exception);
1413 _Py_IDENTIFIER(future);
1414 _Py_IDENTIFIER(source_traceback);
1415
Serhiy Storchakabca49392017-09-03 08:10:14 +03001416 PyObject *error_type, *error_value, *error_traceback;
1417 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001418 PyObject *message = NULL;
1419 PyObject *func;
1420
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001421 if (!fut->fut_log_tb) {
1422 return;
1423 }
1424 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001425 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001426
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001427 /* Save the current exception, if any. */
1428 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1429
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001430 context = PyDict_New();
1431 if (context == NULL) {
1432 goto finally;
1433 }
1434
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001435 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001436 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001437 if (message == NULL) {
1438 goto finally;
1439 }
1440
1441 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1442 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1443 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1444 goto finally;
1445 }
1446 if (fut->fut_source_tb != NULL) {
1447 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1448 fut->fut_source_tb) < 0) {
1449 goto finally;
1450 }
1451 }
1452
1453 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1454 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01001455 PyObject *res = PyObject_CallOneArg(func, context);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001456 if (res == NULL) {
1457 PyErr_WriteUnraisable(func);
1458 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001459 else {
1460 Py_DECREF(res);
1461 }
1462 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001463 }
1464
1465finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001466 Py_XDECREF(context);
1467 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001468
1469 /* Restore the saved exception. */
1470 PyErr_Restore(error_type, error_value, error_traceback);
1471}
1472
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001473static PyObject *
1474future_cls_getitem(PyObject *cls, PyObject *type)
1475{
1476 Py_INCREF(cls);
1477 return cls;
1478}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001479
1480static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001481 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001482 0, /* am_aiter */
1483 0 /* am_anext */
1484};
1485
1486static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001487 _ASYNCIO_FUTURE_RESULT_METHODDEF
1488 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1489 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1490 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1491 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1492 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1493 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1494 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1495 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001496 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001497 _ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001498 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001499 {"__class_getitem__", future_cls_getitem, METH_O|METH_CLASS, NULL},
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001500 {NULL, NULL} /* Sentinel */
1501};
1502
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001503#define FUTURE_COMMON_GETSETLIST \
1504 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1505 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1506 (setter)FutureObj_set_blocking, NULL}, \
1507 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1508 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1509 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1510 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001511 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1512 (setter)FutureObj_set_log_traceback, NULL}, \
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001513 {"_source_traceback", (getter)FutureObj_get_source_traceback, \
1514 NULL, NULL}, \
1515 {"_cancel_message", (getter)FutureObj_get_cancel_message, \
1516 (setter)FutureObj_set_cancel_message, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001517
1518static PyGetSetDef FutureType_getsetlist[] = {
1519 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001520 {NULL} /* Sentinel */
1521};
1522
1523static void FutureObj_dealloc(PyObject *self);
1524
1525static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001526 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001527 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001528 sizeof(FutureObj), /* tp_basicsize */
1529 .tp_dealloc = FutureObj_dealloc,
1530 .tp_as_async = &FutureType_as_async,
1531 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001532 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001533 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001534 .tp_traverse = (traverseproc)FutureObj_traverse,
1535 .tp_clear = (inquiry)FutureObj_clear,
1536 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001537 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001538 .tp_methods = FutureType_methods,
1539 .tp_getset = FutureType_getsetlist,
1540 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001541 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001542 .tp_new = PyType_GenericNew,
1543 .tp_finalize = (destructor)FutureObj_finalize,
1544};
1545
1546static void
1547FutureObj_dealloc(PyObject *self)
1548{
1549 FutureObj *fut = (FutureObj *)self;
1550
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001551 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001552 /* When fut is subclass of Future, finalizer is called from
1553 * subtype_dealloc.
1554 */
1555 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1556 // resurrected.
1557 return;
1558 }
1559 }
1560
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001561 PyObject_GC_UnTrack(self);
1562
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001563 if (fut->fut_weakreflist != NULL) {
1564 PyObject_ClearWeakRefs(self);
1565 }
1566
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001567 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001568 Py_TYPE(fut)->tp_free(fut);
1569}
1570
1571
1572/*********************** Future Iterator **************************/
1573
1574typedef struct {
1575 PyObject_HEAD
1576 FutureObj *future;
1577} futureiterobject;
1578
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001579
1580#define FI_FREELIST_MAXLEN 255
1581static futureiterobject *fi_freelist = NULL;
1582static Py_ssize_t fi_freelist_len = 0;
1583
1584
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001585static void
1586FutureIter_dealloc(futureiterobject *it)
1587{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001588 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001589 Py_CLEAR(it->future);
1590
1591 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1592 fi_freelist_len++;
1593 it->future = (FutureObj*) fi_freelist;
1594 fi_freelist = it;
1595 }
1596 else {
1597 PyObject_GC_Del(it);
1598 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001599}
1600
1601static PyObject *
1602FutureIter_iternext(futureiterobject *it)
1603{
1604 PyObject *res;
1605 FutureObj *fut = it->future;
1606
1607 if (fut == NULL) {
1608 return NULL;
1609 }
1610
1611 if (fut->fut_state == STATE_PENDING) {
1612 if (!fut->fut_blocking) {
1613 fut->fut_blocking = 1;
1614 Py_INCREF(fut);
1615 return (PyObject *)fut;
1616 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001617 PyErr_SetString(PyExc_RuntimeError,
1618 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001619 return NULL;
1620 }
1621
Serhiy Storchakabca49392017-09-03 08:10:14 +03001622 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001623 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001624 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001625 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001626 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001627 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001628 }
1629
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001630 Py_DECREF(fut);
1631 return NULL;
1632}
1633
1634static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001635FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001636{
INADA Naoki74c17532016-10-25 19:00:45 +09001637 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001638 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001639 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001640 return FutureIter_iternext(self);
1641}
1642
1643static PyObject *
1644FutureIter_throw(futureiterobject *self, PyObject *args)
1645{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001646 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001647 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1648 return NULL;
1649
1650 if (val == Py_None) {
1651 val = NULL;
1652 }
1653 if (tb == Py_None) {
1654 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001655 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1656 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1657 return NULL;
1658 }
1659
1660 Py_INCREF(type);
1661 Py_XINCREF(val);
1662 Py_XINCREF(tb);
1663
1664 if (PyExceptionClass_Check(type)) {
1665 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001666 /* No need to call PyException_SetTraceback since we'll be calling
1667 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001668 } else if (PyExceptionInstance_Check(type)) {
1669 if (val) {
1670 PyErr_SetString(PyExc_TypeError,
1671 "instance exception may not have a separate value");
1672 goto fail;
1673 }
1674 val = type;
1675 type = PyExceptionInstance_Class(type);
1676 Py_INCREF(type);
1677 if (tb == NULL)
1678 tb = PyException_GetTraceback(val);
1679 } else {
1680 PyErr_SetString(PyExc_TypeError,
1681 "exceptions must be classes deriving BaseException or "
1682 "instances of such a class");
1683 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001684 }
1685
1686 Py_CLEAR(self->future);
1687
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001688 PyErr_Restore(type, val, tb);
1689
Serhiy Storchakabca49392017-09-03 08:10:14 +03001690 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001691
1692 fail:
1693 Py_DECREF(type);
1694 Py_XDECREF(val);
1695 Py_XDECREF(tb);
1696 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001697}
1698
1699static PyObject *
1700FutureIter_close(futureiterobject *self, PyObject *arg)
1701{
1702 Py_CLEAR(self->future);
1703 Py_RETURN_NONE;
1704}
1705
1706static int
1707FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1708{
1709 Py_VISIT(it->future);
1710 return 0;
1711}
1712
1713static PyMethodDef FutureIter_methods[] = {
1714 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1715 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1716 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1717 {NULL, NULL} /* Sentinel */
1718};
1719
1720static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001721 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001722 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001723 .tp_basicsize = sizeof(futureiterobject),
1724 .tp_itemsize = 0,
1725 .tp_dealloc = (destructor)FutureIter_dealloc,
1726 .tp_getattro = PyObject_GenericGetAttr,
1727 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1728 .tp_traverse = (traverseproc)FutureIter_traverse,
1729 .tp_iter = PyObject_SelfIter,
1730 .tp_iternext = (iternextfunc)FutureIter_iternext,
1731 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001732};
1733
1734static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001735future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001736{
1737 futureiterobject *it;
1738
1739 if (!PyObject_TypeCheck(fut, &FutureType)) {
1740 PyErr_BadInternalCall();
1741 return NULL;
1742 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001743
1744 ENSURE_FUTURE_ALIVE(fut)
1745
1746 if (fi_freelist_len) {
1747 fi_freelist_len--;
1748 it = fi_freelist;
1749 fi_freelist = (futureiterobject*) it->future;
1750 it->future = NULL;
1751 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001752 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001753 else {
1754 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1755 if (it == NULL) {
1756 return NULL;
1757 }
1758 }
1759
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001760 Py_INCREF(fut);
1761 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001762 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001763 return (PyObject*)it;
1764}
1765
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001766
1767/*********************** Task **************************/
1768
1769
1770/*[clinic input]
1771class _asyncio.Task "TaskObj *" "&Task_Type"
1772[clinic start generated code]*/
1773/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1774
1775static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001776static PyObject * task_wakeup(TaskObj *, PyObject *);
1777static PyObject * task_step(TaskObj *, PyObject *);
1778
1779/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001780
INADA Naokic411a7d2016-10-18 11:48:14 +09001781static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001782TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001783{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001784 Py_CLEAR(o->sw_task);
1785 Py_CLEAR(o->sw_arg);
1786 return 0;
1787}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001788
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001789static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001790TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001791{
1792 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001793 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001794 Py_TYPE(o)->tp_free(o);
1795}
1796
1797static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001798TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001799 PyObject *args, PyObject *kwds)
1800{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001801 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1802 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1803 return NULL;
1804 }
1805 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1806 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1807 return NULL;
1808 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001809 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001810}
1811
1812static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001813TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001814 visitproc visit, void *arg)
1815{
1816 Py_VISIT(o->sw_task);
1817 Py_VISIT(o->sw_arg);
1818 return 0;
1819}
1820
1821static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001822TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001823{
1824 if (o->sw_task) {
1825 Py_INCREF(o->sw_task);
1826 return (PyObject*)o->sw_task;
1827 }
1828 Py_RETURN_NONE;
1829}
1830
Serhiy Storchakabca49392017-09-03 08:10:14 +03001831static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1832 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001833 {NULL} /* Sentinel */
1834};
1835
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001836static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001837 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001838 "TaskStepMethWrapper",
1839 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001840 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001841 .tp_getset = TaskStepMethWrapper_getsetlist,
1842 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1843 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001844 .tp_getattro = PyObject_GenericGetAttr,
1845 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001846 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1847 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001848};
1849
1850static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001851TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001852{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001853 TaskStepMethWrapper *o;
1854 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001855 if (o == NULL) {
1856 return NULL;
1857 }
1858
1859 Py_INCREF(task);
1860 o->sw_task = task;
1861
1862 Py_XINCREF(arg);
1863 o->sw_arg = arg;
1864
1865 PyObject_GC_Track(o);
1866 return (PyObject*) o;
1867}
1868
1869/* ----- Task._wakeup wrapper */
1870
1871static PyObject *
1872TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1873 PyObject *args, PyObject *kwds)
1874{
1875 PyObject *fut;
1876
Serhiy Storchakabca49392017-09-03 08:10:14 +03001877 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1878 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1879 return NULL;
1880 }
1881 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001882 return NULL;
1883 }
1884
Yury Selivanov22feeb82018-01-24 11:31:01 -05001885 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001886}
1887
1888static int
1889TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1890{
1891 Py_CLEAR(o->ww_task);
1892 return 0;
1893}
1894
1895static int
1896TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1897 visitproc visit, void *arg)
1898{
1899 Py_VISIT(o->ww_task);
1900 return 0;
1901}
1902
1903static void
1904TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1905{
1906 PyObject_GC_UnTrack(o);
1907 (void)TaskWakeupMethWrapper_clear(o);
1908 Py_TYPE(o)->tp_free(o);
1909}
1910
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001911static PyObject *
1912TaskWakeupMethWrapper_get___self__(TaskWakeupMethWrapper *o, void *Py_UNUSED(ignored))
1913{
1914 if (o->ww_task) {
1915 Py_INCREF(o->ww_task);
1916 return (PyObject*)o->ww_task;
1917 }
1918 Py_RETURN_NONE;
1919}
1920
1921static PyGetSetDef TaskWakeupMethWrapper_getsetlist[] = {
1922 {"__self__", (getter)TaskWakeupMethWrapper_get___self__, NULL, NULL},
1923 {NULL} /* Sentinel */
1924};
1925
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001926static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001927 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001928 "TaskWakeupMethWrapper",
1929 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1930 .tp_itemsize = 0,
1931 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1932 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1933 .tp_getattro = PyObject_GenericGetAttr,
1934 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1935 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1936 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001937 .tp_getset = TaskWakeupMethWrapper_getsetlist,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001938};
1939
1940static PyObject *
1941TaskWakeupMethWrapper_new(TaskObj *task)
1942{
1943 TaskWakeupMethWrapper *o;
1944 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1945 if (o == NULL) {
1946 return NULL;
1947 }
1948
1949 Py_INCREF(task);
1950 o->ww_task = task;
1951
1952 PyObject_GC_Track(o);
1953 return (PyObject*) o;
1954}
1955
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001956/* ----- Task introspection helpers */
1957
1958static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001959register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001960{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001961 _Py_IDENTIFIER(add);
1962
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001963 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1964 &PyId_add, task);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001965 if (res == NULL) {
1966 return -1;
1967 }
1968 Py_DECREF(res);
1969 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001970}
1971
1972
1973static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001974unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001975{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001976 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001977
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001978 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1979 &PyId_discard, task);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001980 if (res == NULL) {
1981 return -1;
1982 }
1983 Py_DECREF(res);
1984 return 0;
1985}
1986
1987
1988static int
1989enter_task(PyObject *loop, PyObject *task)
1990{
1991 PyObject *item;
1992 Py_hash_t hash;
1993 hash = PyObject_Hash(loop);
1994 if (hash == -1) {
1995 return -1;
1996 }
1997 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1998 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03001999 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002000 PyErr_Format(
2001 PyExc_RuntimeError,
2002 "Cannot enter into task %R while another " \
2003 "task %R is being executed.",
2004 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002005 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002006 return -1;
2007 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03002008 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002009 return -1;
2010 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03002011 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002012}
2013
2014
2015static int
2016leave_task(PyObject *loop, PyObject *task)
2017/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
2018{
2019 PyObject *item;
2020 Py_hash_t hash;
2021 hash = PyObject_Hash(loop);
2022 if (hash == -1) {
2023 return -1;
2024 }
2025 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
2026 if (item != task) {
2027 if (item == NULL) {
2028 /* Not entered, replace with None */
2029 item = Py_None;
2030 }
2031 PyErr_Format(
2032 PyExc_RuntimeError,
2033 "Leaving task %R does not match the current task %R.",
2034 task, item, NULL);
2035 return -1;
2036 }
2037 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
2038}
2039
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002040/* ----- Task */
2041
2042/*[clinic input]
2043_asyncio.Task.__init__
2044
Serhiy Storchakabca49392017-09-03 08:10:14 +03002045 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002046 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002047 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002048 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002049
2050A coroutine wrapped in a Future.
2051[clinic start generated code]*/
2052
2053static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002054_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2055 PyObject *name)
2056/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002057{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002058 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002059 return -1;
2060 }
INADA Naokic411a7d2016-10-18 11:48:14 +09002061
Yury Selivanova9d7e552017-12-19 07:18:45 -05002062 int is_coro = is_coroutine(coro);
2063 if (is_coro == -1) {
2064 return -1;
2065 }
2066 if (is_coro == 0) {
2067 self->task_log_destroy_pending = 0;
2068 PyErr_Format(PyExc_TypeError,
2069 "a coroutine was expected, got %R",
2070 coro, NULL);
2071 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02002072 }
2073
Oren Milmand019bc82018-02-13 12:28:33 +02002074 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05002075 if (self->task_context == NULL) {
2076 return -1;
2077 }
2078
Oren Milmand019bc82018-02-13 12:28:33 +02002079 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002080 self->task_must_cancel = 0;
2081 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002082 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02002083 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002084
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002085 if (name == Py_None) {
2086 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03002087 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002088 name = PyObject_Str(name);
2089 } else {
2090 Py_INCREF(name);
2091 }
2092 Py_XSETREF(self->task_name, name);
2093 if (self->task_name == NULL) {
2094 return -1;
2095 }
2096
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002097 if (task_call_step_soon(self, NULL)) {
2098 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09002099 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002100 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002101}
2102
2103static int
2104TaskObj_clear(TaskObj *task)
2105{
2106 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002107 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002108 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002109 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002110 Py_CLEAR(task->task_fut_waiter);
2111 return 0;
2112}
2113
2114static int
2115TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2116{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002117 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002118 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002119 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002120 Py_VISIT(task->task_fut_waiter);
2121 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2122 return 0;
2123}
2124
2125static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002126TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002127{
2128 if (task->task_log_destroy_pending) {
2129 Py_RETURN_TRUE;
2130 }
2131 else {
2132 Py_RETURN_FALSE;
2133 }
2134}
2135
2136static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002137TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002138{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002139 if (val == NULL) {
2140 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2141 return -1;
2142 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002143 int is_true = PyObject_IsTrue(val);
2144 if (is_true < 0) {
2145 return -1;
2146 }
2147 task->task_log_destroy_pending = is_true;
2148 return 0;
2149}
2150
2151static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002152TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002153{
2154 if (task->task_must_cancel) {
2155 Py_RETURN_TRUE;
2156 }
2157 else {
2158 Py_RETURN_FALSE;
2159 }
2160}
2161
2162static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002163TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002164{
2165 if (task->task_coro) {
2166 Py_INCREF(task->task_coro);
2167 return task->task_coro;
2168 }
2169
2170 Py_RETURN_NONE;
2171}
2172
2173static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002174TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002175{
2176 if (task->task_fut_waiter) {
2177 Py_INCREF(task->task_fut_waiter);
2178 return task->task_fut_waiter;
2179 }
2180
2181 Py_RETURN_NONE;
2182}
2183
2184/*[clinic input]
2185@classmethod
2186_asyncio.Task.current_task
2187
Serhiy Storchakabca49392017-09-03 08:10:14 +03002188 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002189
2190Return the currently running task in an event loop or None.
2191
2192By default the current task for the current event loop is returned.
2193
2194None is returned when called not in the context of a Task.
2195[clinic start generated code]*/
2196
2197static PyObject *
2198_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002199/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002200{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002201 PyObject *ret;
2202 PyObject *current_task_func;
2203
Inada Naokic5c6cda2019-03-22 20:07:32 +09002204 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002205 "Task.current_task() is deprecated, " \
2206 "use asyncio.current_task() instead",
2207 1) < 0) {
2208 return NULL;
2209 }
2210
2211 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2212 if (current_task_func == NULL) {
2213 return NULL;
2214 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002215
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002216 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002217 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002218 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002219 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002220 return NULL;
2221 }
Petr Viktorinffd97532020-02-11 17:46:57 +01002222 ret = PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002223 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002224 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002225 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002226 }
2227 else {
Petr Viktorinffd97532020-02-11 17:46:57 +01002228 ret = PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002229 Py_DECREF(current_task_func);
2230 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002231 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002232}
2233
2234/*[clinic input]
2235@classmethod
2236_asyncio.Task.all_tasks
2237
Serhiy Storchakabca49392017-09-03 08:10:14 +03002238 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002239
2240Return a set of all tasks for an event loop.
2241
2242By default all tasks for the current event loop are returned.
2243[clinic start generated code]*/
2244
2245static PyObject *
2246_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002247/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002248{
2249 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002250 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002251
Inada Naokic5c6cda2019-03-22 20:07:32 +09002252 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002253 "Task.all_tasks() is deprecated, " \
2254 "use asyncio.all_tasks() instead",
2255 1) < 0) {
2256 return NULL;
2257 }
2258
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002259 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002260 if (all_tasks_func == NULL) {
2261 return NULL;
2262 }
2263
Petr Viktorinffd97532020-02-11 17:46:57 +01002264 res = PyObject_CallOneArg(all_tasks_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002265 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002266 return res;
2267}
2268
2269/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002270_asyncio.Task._make_cancelled_error
2271
2272Create the CancelledError to raise if the Task is cancelled.
2273
2274This should only be called once when handling a cancellation since
2275it erases the context exception value.
2276[clinic start generated code]*/
2277
2278static PyObject *
2279_asyncio_Task__make_cancelled_error_impl(TaskObj *self)
2280/*[clinic end generated code: output=55a819e8b4276fab input=52c0e32de8e2f840]*/
2281{
2282 FutureObj *fut = (FutureObj*)self;
2283 return _asyncio_Future__make_cancelled_error_impl(fut);
2284}
2285
2286
2287/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002288_asyncio.Task._repr_info
2289[clinic start generated code]*/
2290
2291static PyObject *
2292_asyncio_Task__repr_info_impl(TaskObj *self)
2293/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2294{
Petr Viktorinffd97532020-02-11 17:46:57 +01002295 return PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002296}
2297
2298/*[clinic input]
2299_asyncio.Task.cancel
2300
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002301 msg: object = None
2302
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002303Request that this task cancel itself.
2304
2305This arranges for a CancelledError to be thrown into the
2306wrapped coroutine on the next cycle through the event loop.
2307The coroutine then has a chance to clean up or even deny
2308the request using try/except/finally.
2309
2310Unlike Future.cancel, this does not guarantee that the
2311task will be cancelled: the exception might be caught and
2312acted upon, delaying cancellation of the task or preventing
2313cancellation completely. The task may also return a value or
2314raise a different exception.
2315
2316Immediately after this method is called, Task.cancelled() will
2317not return True (unless the task was already cancelled). A
2318task will be marked as cancelled when the wrapped coroutine
2319terminates with a CancelledError exception (even if cancel()
2320was not called).
2321[clinic start generated code]*/
2322
2323static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002324_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
2325/*[clinic end generated code: output=c66b60d41c74f9f1 input=f4ff8e8ffc5f1c00]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002326{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002327 self->task_log_tb = 0;
2328
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002329 if (self->task_state != STATE_PENDING) {
2330 Py_RETURN_FALSE;
2331 }
2332
2333 if (self->task_fut_waiter) {
2334 PyObject *res;
2335 int is_true;
2336
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002337 res = _PyObject_CallMethodIdOneArg(self->task_fut_waiter,
2338 &PyId_cancel, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002339 if (res == NULL) {
2340 return NULL;
2341 }
2342
2343 is_true = PyObject_IsTrue(res);
2344 Py_DECREF(res);
2345 if (is_true < 0) {
2346 return NULL;
2347 }
2348
2349 if (is_true) {
2350 Py_RETURN_TRUE;
2351 }
2352 }
2353
2354 self->task_must_cancel = 1;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002355 Py_XINCREF(msg);
2356 Py_XSETREF(self->task_cancel_msg, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002357 Py_RETURN_TRUE;
2358}
2359
2360/*[clinic input]
2361_asyncio.Task.get_stack
2362
2363 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002364 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002365
2366Return the list of stack frames for this task's coroutine.
2367
2368If the coroutine is not done, this returns the stack where it is
2369suspended. If the coroutine has completed successfully or was
2370cancelled, this returns an empty list. If the coroutine was
2371terminated by an exception, this returns the list of traceback
2372frames.
2373
2374The frames are always ordered from oldest to newest.
2375
2376The optional limit gives the maximum number of frames to
2377return; by default all available frames are returned. Its
2378meaning differs depending on whether a stack or a traceback is
2379returned: the newest frames of a stack are returned, but the
2380oldest frames of a traceback are returned. (This matches the
2381behavior of the traceback module.)
2382
2383For reasons beyond our control, only one stack frame is
2384returned for a suspended coroutine.
2385[clinic start generated code]*/
2386
2387static PyObject *
2388_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002389/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002390{
2391 return PyObject_CallFunctionObjArgs(
2392 asyncio_task_get_stack_func, self, limit, NULL);
2393}
2394
2395/*[clinic input]
2396_asyncio.Task.print_stack
2397
2398 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002399 limit: object = None
2400 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002401
2402Print the stack or traceback for this task's coroutine.
2403
2404This produces output similar to that of the traceback module,
2405for the frames retrieved by get_stack(). The limit argument
2406is passed to get_stack(). The file argument is an I/O stream
2407to which the output is written; by default output is written
2408to sys.stderr.
2409[clinic start generated code]*/
2410
2411static PyObject *
2412_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2413 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002414/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002415{
2416 return PyObject_CallFunctionObjArgs(
2417 asyncio_task_print_stack_func, self, limit, file, NULL);
2418}
2419
2420/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002421_asyncio.Task.set_result
2422
2423 result: object
2424 /
2425[clinic start generated code]*/
2426
2427static PyObject *
2428_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2429/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2430{
2431 PyErr_SetString(PyExc_RuntimeError,
2432 "Task does not support set_result operation");
2433 return NULL;
2434}
2435
2436/*[clinic input]
2437_asyncio.Task.set_exception
2438
2439 exception: object
2440 /
2441[clinic start generated code]*/
2442
2443static PyObject *
2444_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2445/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2446{
2447 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002448 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002449 return NULL;
2450}
2451
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002452/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002453_asyncio.Task.get_coro
2454[clinic start generated code]*/
2455
2456static PyObject *
2457_asyncio_Task_get_coro_impl(TaskObj *self)
2458/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2459{
2460 Py_INCREF(self->task_coro);
2461 return self->task_coro;
2462}
2463
2464/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002465_asyncio.Task.get_name
2466[clinic start generated code]*/
2467
2468static PyObject *
2469_asyncio_Task_get_name_impl(TaskObj *self)
2470/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2471{
2472 if (self->task_name) {
2473 Py_INCREF(self->task_name);
2474 return self->task_name;
2475 }
2476
2477 Py_RETURN_NONE;
2478}
2479
2480/*[clinic input]
2481_asyncio.Task.set_name
2482
2483 value: object
2484 /
2485[clinic start generated code]*/
2486
2487static PyObject *
2488_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2489/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2490{
Alex Grönholma7548232018-08-09 23:49:49 +03002491 if (!PyUnicode_CheckExact(value)) {
2492 value = PyObject_Str(value);
2493 if (value == NULL) {
2494 return NULL;
2495 }
2496 } else {
2497 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002498 }
2499
Alex Grönholma7548232018-08-09 23:49:49 +03002500 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002501 Py_RETURN_NONE;
2502}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002503
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002504static void
2505TaskObj_finalize(TaskObj *task)
2506{
2507 _Py_IDENTIFIER(call_exception_handler);
2508 _Py_IDENTIFIER(task);
2509 _Py_IDENTIFIER(message);
2510 _Py_IDENTIFIER(source_traceback);
2511
Serhiy Storchakabca49392017-09-03 08:10:14 +03002512 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002513 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002514 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002515 PyObject *error_type, *error_value, *error_traceback;
2516
2517 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2518 goto done;
2519 }
2520
2521 /* Save the current exception, if any. */
2522 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2523
2524 context = PyDict_New();
2525 if (context == NULL) {
2526 goto finally;
2527 }
2528
2529 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2530 if (message == NULL) {
2531 goto finally;
2532 }
2533
2534 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2535 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2536 {
2537 goto finally;
2538 }
2539
2540 if (task->task_source_tb != NULL) {
2541 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2542 task->task_source_tb) < 0)
2543 {
2544 goto finally;
2545 }
2546 }
2547
2548 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2549 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01002550 PyObject *res = PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002551 if (res == NULL) {
2552 PyErr_WriteUnraisable(func);
2553 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002554 else {
2555 Py_DECREF(res);
2556 }
2557 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002558 }
2559
2560finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002561 Py_XDECREF(context);
2562 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002563
2564 /* Restore the saved exception. */
2565 PyErr_Restore(error_type, error_value, error_traceback);
2566
2567done:
2568 FutureObj_finalize((FutureObj*)task);
2569}
2570
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002571static PyObject *
2572task_cls_getitem(PyObject *cls, PyObject *type)
2573{
2574 Py_INCREF(cls);
2575 return cls;
2576}
2577
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002578static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2579
2580static PyMethodDef TaskType_methods[] = {
2581 _ASYNCIO_FUTURE_RESULT_METHODDEF
2582 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002583 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2584 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2585 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2586 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002587 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2588 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002589 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2590 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2591 _ASYNCIO_TASK_CANCEL_METHODDEF
2592 _ASYNCIO_TASK_GET_STACK_METHODDEF
2593 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002594 _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002595 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002596 _ASYNCIO_TASK_GET_NAME_METHODDEF
2597 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002598 _ASYNCIO_TASK_GET_CORO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002599 {"__class_getitem__", task_cls_getitem, METH_O|METH_CLASS, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002600 {NULL, NULL} /* Sentinel */
2601};
2602
2603static PyGetSetDef TaskType_getsetlist[] = {
2604 FUTURE_COMMON_GETSETLIST
2605 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2606 (setter)TaskObj_set_log_destroy_pending, NULL},
2607 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2608 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2609 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2610 {NULL} /* Sentinel */
2611};
2612
2613static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002614 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002615 "_asyncio.Task",
2616 sizeof(TaskObj), /* tp_basicsize */
2617 .tp_base = &FutureType,
2618 .tp_dealloc = TaskObj_dealloc,
2619 .tp_as_async = &FutureType_as_async,
2620 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002621 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002622 .tp_doc = _asyncio_Task___init____doc__,
2623 .tp_traverse = (traverseproc)TaskObj_traverse,
2624 .tp_clear = (inquiry)TaskObj_clear,
2625 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2626 .tp_iter = (getiterfunc)future_new_iter,
2627 .tp_methods = TaskType_methods,
2628 .tp_getset = TaskType_getsetlist,
2629 .tp_dictoffset = offsetof(TaskObj, dict),
2630 .tp_init = (initproc)_asyncio_Task___init__,
2631 .tp_new = PyType_GenericNew,
2632 .tp_finalize = (destructor)TaskObj_finalize,
2633};
2634
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002635static void
2636TaskObj_dealloc(PyObject *self)
2637{
2638 TaskObj *task = (TaskObj *)self;
2639
2640 if (Task_CheckExact(self)) {
2641 /* When fut is subclass of Task, finalizer is called from
2642 * subtype_dealloc.
2643 */
2644 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2645 // resurrected.
2646 return;
2647 }
2648 }
2649
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002650 PyObject_GC_UnTrack(self);
2651
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002652 if (task->task_weakreflist != NULL) {
2653 PyObject_ClearWeakRefs(self);
2654 }
2655
2656 (void)TaskObj_clear(task);
2657 Py_TYPE(task)->tp_free(task);
2658}
2659
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002660static int
2661task_call_step_soon(TaskObj *task, PyObject *arg)
2662{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002663 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002664 if (cb == NULL) {
2665 return -1;
2666 }
2667
Yury Selivanovf23746a2018-01-22 19:11:18 -05002668 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002669 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002670 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002671}
2672
2673static PyObject *
2674task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2675{
2676 PyObject* msg;
2677
2678 va_list vargs;
2679#ifdef HAVE_STDARG_PROTOTYPES
2680 va_start(vargs, format);
2681#else
2682 va_start(vargs);
2683#endif
2684 msg = PyUnicode_FromFormatV(format, vargs);
2685 va_end(vargs);
2686
2687 if (msg == NULL) {
2688 return NULL;
2689 }
2690
Petr Viktorinffd97532020-02-11 17:46:57 +01002691 PyObject *e = PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002692 Py_DECREF(msg);
2693 if (e == NULL) {
2694 return NULL;
2695 }
2696
2697 if (task_call_step_soon(task, e) == -1) {
2698 Py_DECREF(e);
2699 return NULL;
2700 }
2701
2702 Py_DECREF(e);
2703 Py_RETURN_NONE;
2704}
2705
2706static PyObject *
2707task_step_impl(TaskObj *task, PyObject *exc)
2708{
2709 int res;
2710 int clear_exc = 0;
2711 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002712 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002713 PyObject *o;
2714
2715 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002716 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002717 "_step(): already done: %R %R",
2718 task,
2719 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002720 goto fail;
2721 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002722
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002723 if (task->task_must_cancel) {
2724 assert(exc != Py_None);
2725
2726 if (exc) {
2727 /* Check if exc is a CancelledError */
2728 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2729 if (res == -1) {
2730 /* An error occurred, abort */
2731 goto fail;
2732 }
2733 if (res == 0) {
2734 /* exc is not CancelledError; reset it to NULL */
2735 exc = NULL;
2736 }
2737 }
2738
2739 if (!exc) {
2740 /* exc was not a CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002741 exc = create_cancelled_error(task->task_cancel_msg);
2742
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002743 if (!exc) {
2744 goto fail;
2745 }
2746 clear_exc = 1;
2747 }
2748
2749 task->task_must_cancel = 0;
2750 }
2751
2752 Py_CLEAR(task->task_fut_waiter);
2753
Serhiy Storchakabca49392017-09-03 08:10:14 +03002754 coro = task->task_coro;
2755 if (coro == NULL) {
2756 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
Chris Jerdonekd2c349b2020-05-08 03:54:38 -07002757 if (clear_exc) {
2758 /* We created 'exc' during this call */
2759 Py_DECREF(exc);
2760 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002761 return NULL;
2762 }
2763
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002764 if (exc == NULL) {
2765 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2766 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2767 }
2768 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002769 result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002770 }
2771 }
2772 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002773 result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002774 if (clear_exc) {
2775 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002776 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002777 }
2778 }
2779
2780 if (result == NULL) {
2781 PyObject *et, *ev, *tb;
2782
2783 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2784 /* The error is StopIteration and that means that
2785 the underlying coroutine has resolved */
Yury Selivanovedad4d82019-09-25 03:32:08 -07002786
2787 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002788 if (task->task_must_cancel) {
2789 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002790 task->task_must_cancel = 0;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002791 res = future_cancel((FutureObj*)task, task->task_cancel_msg);
INADA Naoki991adca2017-05-11 21:18:38 +09002792 }
Yury Selivanovedad4d82019-09-25 03:32:08 -07002793 else {
2794 res = future_set_result((FutureObj*)task, o);
2795 }
2796
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002797 Py_DECREF(o);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002798
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002799 if (res == NULL) {
2800 return NULL;
2801 }
2802 Py_DECREF(res);
2803 Py_RETURN_NONE;
2804 }
2805
2806 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2807 /* CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002808 PyErr_Fetch(&et, &ev, &tb);
2809
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002810 FutureObj *fut = (FutureObj*)task;
2811 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
2812 exc_state->exc_type = et;
2813 exc_state->exc_value = ev;
2814 exc_state->exc_traceback = tb;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002815
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002816 return future_cancel(fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002817 }
2818
2819 /* Some other exception; pop it and call Task.set_exception() */
2820 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002821
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002822 assert(et);
2823 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2824 PyErr_NormalizeException(&et, &ev, &tb);
2825 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002826 if (tb != NULL) {
2827 PyException_SetTraceback(ev, tb);
2828 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002829 o = future_set_exception((FutureObj*)task, ev);
2830 if (!o) {
2831 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002832 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002833 Py_XDECREF(tb);
2834 Py_XDECREF(ev);
2835 goto fail;
2836 }
2837 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002838 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002839
Yury Selivanov431b5402019-05-27 14:45:12 +02002840 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2841 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2842 {
2843 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002844 PyErr_Restore(et, ev, tb);
2845 goto fail;
2846 }
2847
Serhiy Storchakabca49392017-09-03 08:10:14 +03002848 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002849 Py_XDECREF(tb);
2850 Py_XDECREF(ev);
2851
2852 Py_RETURN_NONE;
2853 }
2854
2855 if (result == (PyObject*)task) {
2856 /* We have a task that wants to await on itself */
2857 goto self_await;
2858 }
2859
2860 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2861 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2862 PyObject *wrapper;
2863 PyObject *res;
2864 FutureObj *fut = (FutureObj*)result;
2865
2866 /* Check if `result` future is attached to a different loop */
2867 if (fut->fut_loop != task->task_loop) {
2868 goto different_loop;
2869 }
2870
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002871 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002872 goto yield_insteadof_yf;
2873 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002874
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002875 fut->fut_blocking = 0;
2876
2877 /* result.add_done_callback(task._wakeup) */
2878 wrapper = TaskWakeupMethWrapper_new(task);
2879 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002880 goto fail;
2881 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002882 res = future_add_done_callback(
2883 (FutureObj*)result, wrapper, task->task_context);
2884 Py_DECREF(wrapper);
2885 if (res == NULL) {
2886 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002887 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002888 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002889
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002890 /* task._fut_waiter = result */
2891 task->task_fut_waiter = result; /* no incref is necessary */
2892
2893 if (task->task_must_cancel) {
2894 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002895 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002896 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2897 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002898 if (r == NULL) {
2899 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002900 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002901 is_true = PyObject_IsTrue(r);
2902 Py_DECREF(r);
2903 if (is_true < 0) {
2904 return NULL;
2905 }
2906 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002907 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002908 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002909 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002910
2911 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002912 }
2913
2914 /* Check if `result` is None */
2915 if (result == Py_None) {
2916 /* Bare yield relinquishes control for one event loop iteration. */
2917 if (task_call_step_soon(task, NULL)) {
2918 goto fail;
2919 }
2920 return result;
2921 }
2922
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002923 /* Check if `result` is a Future-compatible object */
2924 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2925 goto fail;
2926 }
2927 if (o != NULL && o != Py_None) {
2928 /* `result` is a Future-compatible object */
2929 PyObject *wrapper;
2930 PyObject *res;
2931
2932 int blocking = PyObject_IsTrue(o);
2933 Py_DECREF(o);
2934 if (blocking < 0) {
2935 goto fail;
2936 }
2937
2938 /* Check if `result` future is attached to a different loop */
2939 PyObject *oloop = get_future_loop(result);
2940 if (oloop == NULL) {
2941 goto fail;
2942 }
2943 if (oloop != task->task_loop) {
2944 Py_DECREF(oloop);
2945 goto different_loop;
2946 }
2947 Py_DECREF(oloop);
2948
2949 if (!blocking) {
2950 goto yield_insteadof_yf;
2951 }
2952
2953 /* result._asyncio_future_blocking = False */
2954 if (_PyObject_SetAttrId(
2955 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2956 goto fail;
2957 }
2958
2959 wrapper = TaskWakeupMethWrapper_new(task);
2960 if (wrapper == NULL) {
2961 goto fail;
2962 }
2963
2964 /* result.add_done_callback(task._wakeup) */
2965 PyObject *add_cb = _PyObject_GetAttrId(
2966 result, &PyId_add_done_callback);
2967 if (add_cb == NULL) {
2968 Py_DECREF(wrapper);
2969 goto fail;
2970 }
2971 PyObject *stack[2];
2972 stack[0] = wrapper;
2973 stack[1] = (PyObject *)task->task_context;
Petr Viktorinffd97532020-02-11 17:46:57 +01002974 res = PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002975 Py_DECREF(add_cb);
2976 Py_DECREF(wrapper);
2977 if (res == NULL) {
2978 goto fail;
2979 }
2980 Py_DECREF(res);
2981
2982 /* task._fut_waiter = result */
2983 task->task_fut_waiter = result; /* no incref is necessary */
2984
2985 if (task->task_must_cancel) {
2986 PyObject *r;
2987 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002988 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2989 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002990 if (r == NULL) {
2991 return NULL;
2992 }
2993 is_true = PyObject_IsTrue(r);
2994 Py_DECREF(r);
2995 if (is_true < 0) {
2996 return NULL;
2997 }
2998 else if (is_true) {
2999 task->task_must_cancel = 0;
3000 }
3001 }
3002
3003 Py_RETURN_NONE;
3004 }
3005
3006 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003007 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003008 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
3009 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003010 goto fail;
3011 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003012 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003013 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03003014 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003015 task, PyExc_RuntimeError,
3016 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03003017 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003018 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03003019 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003020 }
3021
3022 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03003023 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003024 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03003025 Py_DECREF(result);
3026 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003027
3028self_await:
3029 o = task_set_error_soon(
3030 task, PyExc_RuntimeError,
3031 "Task cannot await on itself: %R", task);
3032 Py_DECREF(result);
3033 return o;
3034
3035yield_insteadof_yf:
3036 o = task_set_error_soon(
3037 task, PyExc_RuntimeError,
3038 "yield was used instead of yield from "
3039 "in task %R with %R",
3040 task, result);
3041 Py_DECREF(result);
3042 return o;
3043
3044different_loop:
3045 o = task_set_error_soon(
3046 task, PyExc_RuntimeError,
3047 "Task %R got Future %R attached to a different loop",
3048 task, result);
3049 Py_DECREF(result);
3050 return o;
3051
3052fail:
3053 Py_XDECREF(result);
3054 return NULL;
3055}
3056
3057static PyObject *
3058task_step(TaskObj *task, PyObject *exc)
3059{
3060 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003061
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003062 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003063 return NULL;
3064 }
3065
3066 res = task_step_impl(task, exc);
3067
3068 if (res == NULL) {
3069 PyObject *et, *ev, *tb;
3070 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003071 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003072 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003073 return NULL;
3074 }
3075 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003076 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003077 Py_DECREF(res);
3078 return NULL;
3079 }
3080 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003081 return res;
3082 }
3083 }
3084}
3085
3086static PyObject *
3087task_wakeup(TaskObj *task, PyObject *o)
3088{
Serhiy Storchakabca49392017-09-03 08:10:14 +03003089 PyObject *et, *ev, *tb;
3090 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003091 assert(o);
3092
3093 if (Future_CheckExact(o) || Task_CheckExact(o)) {
3094 PyObject *fut_result = NULL;
3095 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003096
3097 switch(res) {
3098 case -1:
3099 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003100 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003101 case 0:
3102 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003103 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003104 default:
3105 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003106 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003107 Py_DECREF(fut_result);
3108 return result;
3109 }
3110 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003111 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03003112 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
3113 if (fut_result != NULL) {
3114 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003115 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003116 }
3117 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003118 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003119
3120 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003121 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
3122 PyErr_NormalizeException(&et, &ev, &tb);
3123 }
3124
Yury Selivanov22feeb82018-01-24 11:31:01 -05003125 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003126
3127 Py_DECREF(et);
3128 Py_XDECREF(tb);
3129 Py_XDECREF(ev);
3130
3131 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003132}
3133
3134
Yury Selivanova70232f2017-12-13 14:49:42 -05003135/*********************** Functions **************************/
3136
3137
3138/*[clinic input]
3139_asyncio._get_running_loop
3140
3141Return the running event loop or None.
3142
3143This is a low-level function intended to be used by event loops.
3144This function is thread-specific.
3145
3146[clinic start generated code]*/
3147
3148static PyObject *
3149_asyncio__get_running_loop_impl(PyObject *module)
3150/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3151{
3152 PyObject *loop;
3153 if (get_running_loop(&loop)) {
3154 return NULL;
3155 }
3156 if (loop == NULL) {
3157 /* There's no currently running event loop */
3158 Py_RETURN_NONE;
3159 }
3160 return loop;
3161}
3162
3163/*[clinic input]
3164_asyncio._set_running_loop
3165 loop: 'O'
3166 /
3167
3168Set the running event loop.
3169
3170This is a low-level function intended to be used by event loops.
3171This function is thread-specific.
3172[clinic start generated code]*/
3173
3174static PyObject *
3175_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3176/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3177{
3178 if (set_running_loop(loop)) {
3179 return NULL;
3180 }
3181 Py_RETURN_NONE;
3182}
3183
3184/*[clinic input]
3185_asyncio.get_event_loop
3186
3187Return an asyncio event loop.
3188
3189When called from a coroutine or a callback (e.g. scheduled with
3190call_soon or similar API), this function will always return the
3191running event loop.
3192
3193If there is no running event loop set, the function will return
3194the result of `get_event_loop_policy().get_event_loop()` call.
3195[clinic start generated code]*/
3196
3197static PyObject *
3198_asyncio_get_event_loop_impl(PyObject *module)
3199/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3200{
3201 return get_event_loop();
3202}
3203
3204/*[clinic input]
3205_asyncio.get_running_loop
3206
3207Return the running event loop. Raise a RuntimeError if there is none.
3208
3209This function is thread-specific.
3210[clinic start generated code]*/
3211
3212static PyObject *
3213_asyncio_get_running_loop_impl(PyObject *module)
3214/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3215{
3216 PyObject *loop;
3217 if (get_running_loop(&loop)) {
3218 return NULL;
3219 }
3220 if (loop == NULL) {
3221 /* There's no currently running event loop */
3222 PyErr_SetString(
3223 PyExc_RuntimeError, "no running event loop");
3224 }
3225 return loop;
3226}
3227
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003228/*[clinic input]
3229_asyncio._register_task
3230
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003231 task: object
3232
3233Register a new task in asyncio as executed by loop.
3234
3235Returns None.
3236[clinic start generated code]*/
3237
3238static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003239_asyncio__register_task_impl(PyObject *module, PyObject *task)
3240/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003241{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003242 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003243 return NULL;
3244 }
3245 Py_RETURN_NONE;
3246}
3247
3248
3249/*[clinic input]
3250_asyncio._unregister_task
3251
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003252 task: object
3253
3254Unregister a task.
3255
3256Returns None.
3257[clinic start generated code]*/
3258
3259static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003260_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3261/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003262{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003263 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003264 return NULL;
3265 }
3266 Py_RETURN_NONE;
3267}
3268
3269
3270/*[clinic input]
3271_asyncio._enter_task
3272
3273 loop: object
3274 task: object
3275
3276Enter into task execution or resume suspended task.
3277
3278Task belongs to loop.
3279
3280Returns None.
3281[clinic start generated code]*/
3282
3283static PyObject *
3284_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3285/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3286{
3287 if (enter_task(loop, task) < 0) {
3288 return NULL;
3289 }
3290 Py_RETURN_NONE;
3291}
3292
3293
3294/*[clinic input]
3295_asyncio._leave_task
3296
3297 loop: object
3298 task: object
3299
3300Leave task execution or suspend a task.
3301
3302Task belongs to loop.
3303
3304Returns None.
3305[clinic start generated code]*/
3306
3307static PyObject *
3308_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3309/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3310{
3311 if (leave_task(loop, task) < 0) {
3312 return NULL;
3313 }
3314 Py_RETURN_NONE;
3315}
3316
Yury Selivanova70232f2017-12-13 14:49:42 -05003317
Yury Selivanov9d411c12018-01-23 15:10:03 -05003318/*********************** PyRunningLoopHolder ********************/
3319
3320
3321static PyRunningLoopHolder *
3322new_running_loop_holder(PyObject *loop)
3323{
3324 PyRunningLoopHolder *rl = PyObject_New(
3325 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3326 if (rl == NULL) {
3327 return NULL;
3328 }
3329
3330#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3331 rl->rl_pid = getpid();
3332#endif
3333
3334 Py_INCREF(loop);
3335 rl->rl_loop = loop;
3336
3337 return rl;
3338}
3339
3340
3341static void
3342PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3343{
3344 Py_CLEAR(rl->rl_loop);
3345 PyObject_Free(rl);
3346}
3347
3348
3349static PyTypeObject PyRunningLoopHolder_Type = {
3350 PyVarObject_HEAD_INIT(NULL, 0)
3351 "_RunningLoopHolder",
3352 sizeof(PyRunningLoopHolder),
3353 .tp_getattro = PyObject_GenericGetAttr,
3354 .tp_flags = Py_TPFLAGS_DEFAULT,
3355 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3356};
3357
3358
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003359/*********************** Module **************************/
3360
3361
3362static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003363module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003364{
3365 PyObject *next;
3366 PyObject *current;
3367
3368 next = (PyObject*) fi_freelist;
3369 while (next != NULL) {
3370 assert(fi_freelist_len > 0);
3371 fi_freelist_len--;
3372
3373 current = next;
3374 next = (PyObject*) ((futureiterobject*) current)->future;
3375 PyObject_GC_Del(current);
3376 }
3377 assert(fi_freelist_len == 0);
3378 fi_freelist = NULL;
3379}
3380
3381
3382static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003383module_free(void *m)
3384{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003385 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003386 Py_CLEAR(traceback_extract_stack);
3387 Py_CLEAR(asyncio_future_repr_info_func);
3388 Py_CLEAR(asyncio_get_event_loop_policy);
3389 Py_CLEAR(asyncio_iscoroutine_func);
3390 Py_CLEAR(asyncio_task_get_stack_func);
3391 Py_CLEAR(asyncio_task_print_stack_func);
3392 Py_CLEAR(asyncio_task_repr_info_func);
3393 Py_CLEAR(asyncio_InvalidStateError);
3394 Py_CLEAR(asyncio_CancelledError);
3395
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003396 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003397 Py_CLEAR(current_tasks);
3398 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003399
Yury Selivanovf23746a2018-01-22 19:11:18 -05003400 Py_CLEAR(context_kwname);
3401
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003402 module_free_freelists();
Jeffrey Quesnellea75e7302020-04-16 22:09:45 -04003403
3404 module_initialized = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003405}
3406
3407static int
3408module_init(void)
3409{
3410 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003411
3412 asyncio_mod = PyImport_ImportModule("asyncio");
3413 if (asyncio_mod == NULL) {
3414 goto fail;
3415 }
Ben Harper321def82019-10-07 12:19:58 -04003416 if (module_initialized != 0) {
3417 return 0;
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02003418 }
Ben Harper321def82019-10-07 12:19:58 -04003419 else {
3420 module_initialized = 1;
3421 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003422
3423 current_tasks = PyDict_New();
3424 if (current_tasks == NULL) {
3425 goto fail;
3426 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003427
Yury Selivanova9d7e552017-12-19 07:18:45 -05003428 iscoroutine_typecache = PySet_New(NULL);
3429 if (iscoroutine_typecache == NULL) {
3430 goto fail;
3431 }
3432
Yury Selivanovf23746a2018-01-22 19:11:18 -05003433
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003434 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003435 if (context_kwname == NULL) {
3436 goto fail;
3437 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003438
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003439#define WITH_MOD(NAME) \
3440 Py_CLEAR(module); \
3441 module = PyImport_ImportModule(NAME); \
3442 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003443 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003444 }
3445
3446#define GET_MOD_ATTR(VAR, NAME) \
3447 VAR = PyObject_GetAttrString(module, NAME); \
3448 if (VAR == NULL) { \
3449 goto fail; \
3450 }
3451
3452 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003453 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003454
3455 WITH_MOD("asyncio.base_futures")
3456 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003457
3458 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003459 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3460 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3461
3462 WITH_MOD("asyncio.base_tasks")
3463 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3464 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3465 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3466
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003467 WITH_MOD("asyncio.coroutines")
3468 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3469
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003470 WITH_MOD("traceback")
3471 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3472
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003473 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003474 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003475 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003476 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003477 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003478 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003479 goto fail;
3480 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003481
Serhiy Storchakabca49392017-09-03 08:10:14 +03003482 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003483 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003484
INADA Naokic411a7d2016-10-18 11:48:14 +09003485fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003486 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003487 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003488 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003489
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003490#undef WITH_MOD
3491#undef GET_MOD_ATTR
3492}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003493
INADA Naokic411a7d2016-10-18 11:48:14 +09003494PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003495
Yury Selivanova70232f2017-12-13 14:49:42 -05003496static PyMethodDef asyncio_methods[] = {
3497 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3498 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3499 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3500 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003501 _ASYNCIO__REGISTER_TASK_METHODDEF
3502 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3503 _ASYNCIO__ENTER_TASK_METHODDEF
3504 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003505 {NULL, NULL}
3506};
3507
INADA Naoki9f2ce252016-10-15 15:39:19 +09003508static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003509 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003510 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003511 module_doc, /* m_doc */
3512 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003513 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003514 NULL, /* m_slots */
3515 NULL, /* m_traverse */
3516 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003517 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003518};
3519
3520
3521PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003522PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003523{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003524 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003525 return NULL;
3526 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003527 if (PyType_Ready(&FutureIterType) < 0) {
3528 return NULL;
3529 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003530 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003531 return NULL;
3532 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003533 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003534 return NULL;
3535 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003536 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3537 return NULL;
3538 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003539
INADA Naoki9f2ce252016-10-15 15:39:19 +09003540 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003541 if (m == NULL) {
3542 return NULL;
3543 }
3544
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003545 /* FutureType and TaskType are made ready by PyModule_AddType() calls below. */
3546 if (PyModule_AddType(m, &FutureType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003547 Py_DECREF(m);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003548 return NULL;
3549 }
3550
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003551 if (PyModule_AddType(m, &TaskType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003552 Py_DECREF(m);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003553 return NULL;
3554 }
3555
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003556 Py_INCREF(all_tasks);
3557 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3558 Py_DECREF(all_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003559 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003560 return NULL;
3561 }
3562
3563 Py_INCREF(current_tasks);
3564 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3565 Py_DECREF(current_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003566 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003567 return NULL;
3568 }
3569
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003570 return m;
3571}