blob: 0454f9c6824bf12f0dc0394b99cbb7f217045f97 [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
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700615future_set_cancelled_error(FutureObj *fut)
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700616{
Chris Jerdonek7c30d122020-05-22 13:33:27 -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);
Chris Jerdonek7c30d122020-05-22 13:33:27 -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) {
Chris Jerdonek7c30d122020-05-22 13:33:27 -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) {
Zackery Spytz7b78e7f2020-05-30 02:22:02 -0600713 Py_DECREF(tup);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500714 return NULL;
715 }
716
717 PyList_SET_ITEM(fut->fut_callbacks, 0, tup); /* borrow */
718 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900719 }
720 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500721
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900722 Py_RETURN_NONE;
723}
724
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400725static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700726future_cancel(FutureObj *fut, PyObject *msg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400727{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +0000728 fut->fut_log_tb = 0;
729
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400730 if (fut->fut_state != STATE_PENDING) {
731 Py_RETURN_FALSE;
732 }
733 fut->fut_state = STATE_CANCELLED;
734
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700735 Py_XINCREF(msg);
736 Py_XSETREF(fut->fut_cancel_msg, msg);
737
Yury Selivanov22feeb82018-01-24 11:31:01 -0500738 if (future_schedule_callbacks(fut) == -1) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400739 return NULL;
740 }
741
742 Py_RETURN_TRUE;
743}
744
745/*[clinic input]
746_asyncio.Future.__init__
747
748 *
Serhiy Storchakabca49392017-09-03 08:10:14 +0300749 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400750
751This class is *almost* compatible with concurrent.futures.Future.
752
753 Differences:
754
755 - result() and exception() do not take a timeout argument and
756 raise an exception when the future isn't done yet.
757
758 - Callbacks registered with add_done_callback() are always called
759 via the event loop's call_soon_threadsafe().
760
761 - This class is not compatible with the wait() and as_completed()
762 methods in the concurrent.futures package.
763[clinic start generated code]*/
764
765static int
766_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300767/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400768
769{
770 return future_init(self, loop);
771}
772
773static int
774FutureObj_clear(FutureObj *fut)
775{
776 Py_CLEAR(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500777 Py_CLEAR(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500778 Py_CLEAR(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400779 Py_CLEAR(fut->fut_callbacks);
780 Py_CLEAR(fut->fut_result);
781 Py_CLEAR(fut->fut_exception);
782 Py_CLEAR(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700783 Py_CLEAR(fut->fut_cancel_msg);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700784 _PyErr_ClearExcState(&fut->fut_cancelled_exc_state);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400785 Py_CLEAR(fut->dict);
786 return 0;
787}
788
789static int
790FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
791{
792 Py_VISIT(fut->fut_loop);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500793 Py_VISIT(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500794 Py_VISIT(fut->fut_context0);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400795 Py_VISIT(fut->fut_callbacks);
796 Py_VISIT(fut->fut_result);
797 Py_VISIT(fut->fut_exception);
798 Py_VISIT(fut->fut_source_tb);
Chris Jerdonek1ce58412020-05-15 16:55:50 -0700799 Py_VISIT(fut->fut_cancel_msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400800 Py_VISIT(fut->dict);
Chris Jerdonekda742ba2020-05-17 22:47:31 -0700801
802 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
803 Py_VISIT(exc_state->exc_type);
804 Py_VISIT(exc_state->exc_value);
805 Py_VISIT(exc_state->exc_traceback);
806
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400807 return 0;
808}
809
810/*[clinic input]
811_asyncio.Future.result
812
813Return the result this future represents.
814
815If the future has been cancelled, raises CancelledError. If the
816future's result isn't yet available, raises InvalidStateError. If
817the future is done and has an exception set, this exception is raised.
818[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900819
820static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400821_asyncio_Future_result_impl(FutureObj *self)
822/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
823{
824 PyObject *result;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500825
826 if (!future_is_alive(self)) {
827 PyErr_SetString(asyncio_InvalidStateError,
828 "Future object is not initialized.");
829 return NULL;
830 }
831
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400832 int res = future_get_result(self, &result);
833
834 if (res == -1) {
835 return NULL;
836 }
837
838 if (res == 0) {
839 return result;
840 }
841
842 assert(res == 1);
843
844 PyErr_SetObject(PyExceptionInstance_Class(result), result);
845 Py_DECREF(result);
846 return NULL;
847}
848
849/*[clinic input]
850_asyncio.Future.exception
851
852Return the exception that was set on this future.
853
854The exception (or None if no exception was set) is returned only if
855the future is done. If the future has been cancelled, raises
856CancelledError. If the future isn't done yet, raises
857InvalidStateError.
858[clinic start generated code]*/
859
860static PyObject *
861_asyncio_Future_exception_impl(FutureObj *self)
862/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
863{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500864 if (!future_is_alive(self)) {
865 PyErr_SetString(asyncio_InvalidStateError,
866 "Future object is not initialized.");
867 return NULL;
868 }
869
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400870 if (self->fut_state == STATE_CANCELLED) {
Chris Jerdonek7c30d122020-05-22 13:33:27 -0700871 future_set_cancelled_error(self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400872 return NULL;
873 }
874
875 if (self->fut_state != STATE_FINISHED) {
Serhiy Storchakabca49392017-09-03 08:10:14 +0300876 PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400877 return NULL;
878 }
879
880 if (self->fut_exception != NULL) {
881 self->fut_log_tb = 0;
882 Py_INCREF(self->fut_exception);
883 return self->fut_exception;
884 }
885
886 Py_RETURN_NONE;
887}
888
889/*[clinic input]
890_asyncio.Future.set_result
891
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500892 result: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400893 /
894
895Mark the future done and set its result.
896
897If the future is already done when this method is called, raises
898InvalidStateError.
899[clinic start generated code]*/
900
901static PyObject *
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500902_asyncio_Future_set_result(FutureObj *self, PyObject *result)
903/*[clinic end generated code: output=1ec2e6bcccd6f2ce input=8b75172c2a7b05f1]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400904{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500905 ENSURE_FUTURE_ALIVE(self)
Yury Selivanov0cf16f92017-12-25 10:48:15 -0500906 return future_set_result(self, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400907}
908
909/*[clinic input]
910_asyncio.Future.set_exception
911
Serhiy Storchakabca49392017-09-03 08:10:14 +0300912 exception: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400913 /
914
915Mark the future done and set an exception.
916
917If the future is already done when this method is called, raises
918InvalidStateError.
919[clinic start generated code]*/
920
921static PyObject *
922_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300923/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400924{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500925 ENSURE_FUTURE_ALIVE(self)
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400926 return future_set_exception(self, exception);
927}
928
929/*[clinic input]
930_asyncio.Future.add_done_callback
931
Serhiy Storchakabca49392017-09-03 08:10:14 +0300932 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400933 /
Yury Selivanovf23746a2018-01-22 19:11:18 -0500934 *
935 context: object = NULL
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400936
937Add a callback to be run when the future becomes done.
938
939The callback is called with a single argument - the future object. If
940the future is already done when this is called, the callback is
941scheduled with call_soon.
942[clinic start generated code]*/
943
944static PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500945_asyncio_Future_add_done_callback_impl(FutureObj *self, PyObject *fn,
946 PyObject *context)
947/*[clinic end generated code: output=7ce635bbc9554c1e input=15ab0693a96e9533]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400948{
Yury Selivanovf23746a2018-01-22 19:11:18 -0500949 if (context == NULL) {
Yury Selivanov994269c2018-09-27 14:55:55 -0400950 context = PyContext_CopyCurrent();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500951 if (context == NULL) {
952 return NULL;
953 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400954 PyObject *res = future_add_done_callback(self, fn, context);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500955 Py_DECREF(context);
956 return res;
957 }
Yury Selivanov994269c2018-09-27 14:55:55 -0400958 return future_add_done_callback(self, fn, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400959}
960
961/*[clinic input]
962_asyncio.Future.remove_done_callback
963
Serhiy Storchakabca49392017-09-03 08:10:14 +0300964 fn: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400965 /
966
967Remove all instances of a callback from the "call when done" list.
968
969Returns the number of callbacks removed.
970[clinic start generated code]*/
971
972static PyObject *
973_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
Serhiy Storchakabca49392017-09-03 08:10:14 +0300974/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900975{
976 PyObject *newlist;
977 Py_ssize_t len, i, j=0;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500978 Py_ssize_t cleared_callback0 = 0;
979
980 ENSURE_FUTURE_ALIVE(self)
981
982 if (self->fut_callback0 != NULL) {
Serhiy Storchaka18b711c2019-08-04 14:12:48 +0300983 int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500984 if (cmp == -1) {
985 return NULL;
986 }
987 if (cmp == 1) {
988 /* callback0 == fn */
989 Py_CLEAR(self->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500990 Py_CLEAR(self->fut_context0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500991 cleared_callback0 = 1;
992 }
993 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +0900994
Serhiy Storchakabca49392017-09-03 08:10:14 +0300995 if (self->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -0500996 return PyLong_FromSsize_t(cleared_callback0);
Serhiy Storchakabca49392017-09-03 08:10:14 +0300997 }
998
Yury Selivanova0c1ba62016-10-28 12:52:37 -0400999 len = PyList_GET_SIZE(self->fut_callbacks);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001000 if (len == 0) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001001 Py_CLEAR(self->fut_callbacks);
1002 return PyLong_FromSsize_t(cleared_callback0);
1003 }
1004
1005 if (len == 1) {
Yury Selivanovf23746a2018-01-22 19:11:18 -05001006 PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001007 int cmp = PyObject_RichCompareBool(
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001008 PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001009 if (cmp == -1) {
1010 return NULL;
1011 }
1012 if (cmp == 1) {
1013 /* callbacks[0] == fn */
1014 Py_CLEAR(self->fut_callbacks);
1015 return PyLong_FromSsize_t(1 + cleared_callback0);
1016 }
1017 /* callbacks[0] != fn and len(callbacks) == 1 */
1018 return PyLong_FromSsize_t(cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001019 }
1020
1021 newlist = PyList_New(len);
1022 if (newlist == NULL) {
1023 return NULL;
1024 }
1025
Yury Selivanov84af9032017-03-02 23:46:56 -05001026 for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001027 int ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001028 PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001029 Py_INCREF(item);
Serhiy Storchaka18b711c2019-08-04 14:12:48 +03001030 ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001031 if (ret == 0) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001032 if (j < len) {
Yury Selivanov833a3b02017-07-05 13:32:03 -04001033 PyList_SET_ITEM(newlist, j, item);
1034 j++;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001035 continue;
Yury Selivanov833a3b02017-07-05 13:32:03 -04001036 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001037 ret = PyList_Append(newlist, item);
1038 }
1039 Py_DECREF(item);
1040 if (ret < 0) {
1041 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001042 }
1043 }
1044
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001045 if (j == 0) {
1046 Py_CLEAR(self->fut_callbacks);
1047 Py_DECREF(newlist);
1048 return PyLong_FromSsize_t(len + cleared_callback0);
1049 }
1050
Serhiy Storchakabca49392017-09-03 08:10:14 +03001051 if (j < len) {
Victor Stinner60ac6ed2020-02-07 23:18:08 +01001052 Py_SET_SIZE(newlist, j);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001053 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001054 j = PyList_GET_SIZE(newlist);
1055 len = PyList_GET_SIZE(self->fut_callbacks);
1056 if (j != len) {
1057 if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
1058 goto fail;
1059 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001060 }
1061 Py_DECREF(newlist);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001062 return PyLong_FromSsize_t(len - j + cleared_callback0);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001063
1064fail:
1065 Py_DECREF(newlist);
1066 return NULL;
1067}
1068
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001069/*[clinic input]
1070_asyncio.Future.cancel
1071
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001072 msg: object = None
1073
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001074Cancel the future and schedule callbacks.
1075
1076If the future is already done or cancelled, return False. Otherwise,
1077change the future's state to cancelled, schedule the callbacks and
1078return True.
1079[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001080
1081static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001082_asyncio_Future_cancel_impl(FutureObj *self, PyObject *msg)
1083/*[clinic end generated code: output=3edebbc668e5aba3 input=925eb545251f2c5a]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001084{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001085 ENSURE_FUTURE_ALIVE(self)
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001086 return future_cancel(self, msg);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001087}
1088
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001089/*[clinic input]
1090_asyncio.Future.cancelled
1091
1092Return True if the future was cancelled.
1093[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001094
1095static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001096_asyncio_Future_cancelled_impl(FutureObj *self)
1097/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001098{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001099 if (future_is_alive(self) && self->fut_state == STATE_CANCELLED) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001100 Py_RETURN_TRUE;
1101 }
1102 else {
1103 Py_RETURN_FALSE;
1104 }
1105}
1106
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001107/*[clinic input]
1108_asyncio.Future.done
1109
1110Return True if the future is done.
1111
1112Done means either that a result / exception are available, or that the
1113future was cancelled.
1114[clinic start generated code]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001115
1116static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001117_asyncio_Future_done_impl(FutureObj *self)
1118/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001119{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001120 if (!future_is_alive(self) || self->fut_state == STATE_PENDING) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001121 Py_RETURN_FALSE;
1122 }
1123 else {
1124 Py_RETURN_TRUE;
1125 }
1126}
1127
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001128/*[clinic input]
1129_asyncio.Future.get_loop
1130
1131Return the event loop the Future is bound to.
1132[clinic start generated code]*/
1133
1134static PyObject *
1135_asyncio_Future_get_loop_impl(FutureObj *self)
1136/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
1137{
Andrew Svetlovdad6be52019-11-13 23:36:46 +02001138 ENSURE_FUTURE_ALIVE(self)
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001139 Py_INCREF(self->fut_loop);
1140 return self->fut_loop;
1141}
1142
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001143static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001144FutureObj_get_blocking(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001145{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001146 if (future_is_alive(fut) && fut->fut_blocking) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001147 Py_RETURN_TRUE;
1148 }
1149 else {
1150 Py_RETURN_FALSE;
1151 }
1152}
1153
1154static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001155FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001156{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001157 if (future_ensure_alive(fut)) {
1158 return -1;
1159 }
Zackery Spytz842acaa2018-12-17 07:52:45 -07001160 if (val == NULL) {
1161 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1162 return -1;
1163 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001164
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001165 int is_true = PyObject_IsTrue(val);
1166 if (is_true < 0) {
1167 return -1;
1168 }
1169 fut->fut_blocking = is_true;
1170 return 0;
1171}
1172
1173static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001174FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001175{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001176 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001177 if (fut->fut_log_tb) {
1178 Py_RETURN_TRUE;
1179 }
1180 else {
1181 Py_RETURN_FALSE;
1182 }
1183}
1184
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001185static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001186FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001187{
Zackery Spytz842acaa2018-12-17 07:52:45 -07001188 if (val == NULL) {
1189 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1190 return -1;
1191 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001192 int is_true = PyObject_IsTrue(val);
1193 if (is_true < 0) {
1194 return -1;
1195 }
Yury Selivanove0aef4f2017-12-25 16:16:10 -05001196 if (is_true) {
1197 PyErr_SetString(PyExc_ValueError,
1198 "_log_traceback can only be set to False");
1199 return -1;
1200 }
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001201 fut->fut_log_tb = is_true;
1202 return 0;
1203}
1204
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001205static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001206FutureObj_get_loop(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001207{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001208 if (!future_is_alive(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001209 Py_RETURN_NONE;
1210 }
1211 Py_INCREF(fut->fut_loop);
1212 return fut->fut_loop;
1213}
1214
1215static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001216FutureObj_get_callbacks(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001217{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001218 Py_ssize_t i;
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001219
1220 ENSURE_FUTURE_ALIVE(fut)
1221
Yury Selivanovf23746a2018-01-22 19:11:18 -05001222 if (fut->fut_callback0 == NULL) {
1223 if (fut->fut_callbacks == NULL) {
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001224 Py_RETURN_NONE;
1225 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001226
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001227 Py_INCREF(fut->fut_callbacks);
1228 return fut->fut_callbacks;
1229 }
1230
Yury Selivanovf23746a2018-01-22 19:11:18 -05001231 Py_ssize_t len = 1;
1232 if (fut->fut_callbacks != NULL) {
1233 len += PyList_GET_SIZE(fut->fut_callbacks);
1234 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001235
Yury Selivanovf23746a2018-01-22 19:11:18 -05001236
1237 PyObject *new_list = PyList_New(len);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001238 if (new_list == NULL) {
1239 return NULL;
1240 }
1241
Yury Selivanovf23746a2018-01-22 19:11:18 -05001242 PyObject *tup0 = PyTuple_New(2);
1243 if (tup0 == NULL) {
1244 Py_DECREF(new_list);
1245 return NULL;
1246 }
1247
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001248 Py_INCREF(fut->fut_callback0);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001249 PyTuple_SET_ITEM(tup0, 0, fut->fut_callback0);
1250 assert(fut->fut_context0 != NULL);
1251 Py_INCREF(fut->fut_context0);
1252 PyTuple_SET_ITEM(tup0, 1, (PyObject *)fut->fut_context0);
1253
1254 PyList_SET_ITEM(new_list, 0, tup0);
1255
1256 if (fut->fut_callbacks != NULL) {
1257 for (i = 0; i < PyList_GET_SIZE(fut->fut_callbacks); i++) {
1258 PyObject *cb = PyList_GET_ITEM(fut->fut_callbacks, i);
1259 Py_INCREF(cb);
1260 PyList_SET_ITEM(new_list, i + 1, cb);
1261 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001262 }
1263
1264 return new_list;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001265}
1266
1267static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001268FutureObj_get_result(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001269{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001270 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001271 if (fut->fut_result == NULL) {
1272 Py_RETURN_NONE;
1273 }
1274 Py_INCREF(fut->fut_result);
1275 return fut->fut_result;
1276}
1277
1278static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001279FutureObj_get_exception(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001280{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001281 ENSURE_FUTURE_ALIVE(fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001282 if (fut->fut_exception == NULL) {
1283 Py_RETURN_NONE;
1284 }
1285 Py_INCREF(fut->fut_exception);
1286 return fut->fut_exception;
1287}
1288
1289static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001290FutureObj_get_source_traceback(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001291{
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001292 if (!future_is_alive(fut) || fut->fut_source_tb == NULL) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001293 Py_RETURN_NONE;
1294 }
1295 Py_INCREF(fut->fut_source_tb);
1296 return fut->fut_source_tb;
1297}
1298
1299static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001300FutureObj_get_cancel_message(FutureObj *fut, void *Py_UNUSED(ignored))
1301{
1302 if (fut->fut_cancel_msg == NULL) {
1303 Py_RETURN_NONE;
1304 }
1305 Py_INCREF(fut->fut_cancel_msg);
1306 return fut->fut_cancel_msg;
1307}
1308
1309static int
1310FutureObj_set_cancel_message(FutureObj *fut, PyObject *msg,
1311 void *Py_UNUSED(ignored))
1312{
1313 if (msg == NULL) {
1314 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1315 return -1;
1316 }
1317 Py_INCREF(msg);
1318 Py_XSETREF(fut->fut_cancel_msg, msg);
1319 return 0;
1320}
1321
1322static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001323FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001324{
1325 _Py_IDENTIFIER(PENDING);
1326 _Py_IDENTIFIER(CANCELLED);
1327 _Py_IDENTIFIER(FINISHED);
1328 PyObject *ret = NULL;
1329
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001330 ENSURE_FUTURE_ALIVE(fut)
1331
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001332 switch (fut->fut_state) {
1333 case STATE_PENDING:
1334 ret = _PyUnicode_FromId(&PyId_PENDING);
1335 break;
1336 case STATE_CANCELLED:
1337 ret = _PyUnicode_FromId(&PyId_CANCELLED);
1338 break;
1339 case STATE_FINISHED:
1340 ret = _PyUnicode_FromId(&PyId_FINISHED);
1341 break;
1342 default:
1343 assert (0);
1344 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001345 Py_XINCREF(ret);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001346 return ret;
1347}
1348
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001349/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001350_asyncio.Future._make_cancelled_error
1351
1352Create the CancelledError to raise if the Future is cancelled.
1353
1354This should only be called once when handling a cancellation since
1355it erases the context exception value.
1356[clinic start generated code]*/
1357
1358static PyObject *
1359_asyncio_Future__make_cancelled_error_impl(FutureObj *self)
1360/*[clinic end generated code: output=a5df276f6c1213de input=ac6effe4ba795ecc]*/
1361{
1362 PyObject *exc = create_cancelled_error(self->fut_cancel_msg);
1363 _PyErr_StackItem *exc_state = &self->fut_cancelled_exc_state;
1364 /* Transfer ownership of exc_value from exc_state to exc since we are
1365 done with it. */
1366 PyException_SetContext(exc, exc_state->exc_value);
1367 exc_state->exc_value = NULL;
1368
1369 return exc;
1370}
1371
1372/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001373_asyncio.Future._repr_info
1374[clinic start generated code]*/
1375
1376static PyObject *
1377_asyncio_Future__repr_info_impl(FutureObj *self)
1378/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001379{
Petr Viktorinffd97532020-02-11 17:46:57 +01001380 return PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001381}
1382
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001383static PyObject *
1384FutureObj_repr(FutureObj *fut)
1385{
1386 _Py_IDENTIFIER(_repr_info);
1387
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001388 ENSURE_FUTURE_ALIVE(fut)
1389
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001390 PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
1391 &PyId__repr_info);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001392 if (rinfo == NULL) {
1393 return NULL;
1394 }
1395
Serhiy Storchakabca49392017-09-03 08:10:14 +03001396 PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001397 Py_DECREF(rinfo);
1398 if (rinfo_s == NULL) {
1399 return NULL;
1400 }
1401
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001402 PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
1403 _PyType_Name(Py_TYPE(fut)), rinfo_s);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001404 Py_DECREF(rinfo_s);
1405 return rstr;
1406}
1407
1408static void
1409FutureObj_finalize(FutureObj *fut)
1410{
1411 _Py_IDENTIFIER(call_exception_handler);
1412 _Py_IDENTIFIER(message);
1413 _Py_IDENTIFIER(exception);
1414 _Py_IDENTIFIER(future);
1415 _Py_IDENTIFIER(source_traceback);
1416
Serhiy Storchakabca49392017-09-03 08:10:14 +03001417 PyObject *error_type, *error_value, *error_traceback;
1418 PyObject *context;
Serhiy Storchakabca49392017-09-03 08:10:14 +03001419 PyObject *message = NULL;
1420 PyObject *func;
1421
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001422 if (!fut->fut_log_tb) {
1423 return;
1424 }
1425 assert(fut->fut_exception != NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001426 fut->fut_log_tb = 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001427
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001428 /* Save the current exception, if any. */
1429 PyErr_Fetch(&error_type, &error_value, &error_traceback);
1430
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001431 context = PyDict_New();
1432 if (context == NULL) {
1433 goto finally;
1434 }
1435
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001436 message = PyUnicode_FromFormat(
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001437 "%s exception was never retrieved", _PyType_Name(Py_TYPE(fut)));
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001438 if (message == NULL) {
1439 goto finally;
1440 }
1441
1442 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1443 _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
1444 _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
1445 goto finally;
1446 }
1447 if (fut->fut_source_tb != NULL) {
1448 if (_PyDict_SetItemId(context, &PyId_source_traceback,
1449 fut->fut_source_tb) < 0) {
1450 goto finally;
1451 }
1452 }
1453
1454 func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
1455 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01001456 PyObject *res = PyObject_CallOneArg(func, context);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001457 if (res == NULL) {
1458 PyErr_WriteUnraisable(func);
1459 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03001460 else {
1461 Py_DECREF(res);
1462 }
1463 Py_DECREF(func);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001464 }
1465
1466finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03001467 Py_XDECREF(context);
1468 Py_XDECREF(message);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001469
1470 /* Restore the saved exception. */
1471 PyErr_Restore(error_type, error_value, error_traceback);
1472}
1473
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001474static PyObject *
1475future_cls_getitem(PyObject *cls, PyObject *type)
1476{
1477 Py_INCREF(cls);
1478 return cls;
1479}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001480
1481static PyAsyncMethods FutureType_as_async = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001482 (unaryfunc)future_new_iter, /* am_await */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001483 0, /* am_aiter */
1484 0 /* am_anext */
1485};
1486
1487static PyMethodDef FutureType_methods[] = {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001488 _ASYNCIO_FUTURE_RESULT_METHODDEF
1489 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1490 _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1491 _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1492 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1493 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1494 _ASYNCIO_FUTURE_CANCEL_METHODDEF
1495 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1496 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001497 _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07001498 _ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001499 _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03001500 {"__class_getitem__", future_cls_getitem, METH_O|METH_CLASS, NULL},
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001501 {NULL, NULL} /* Sentinel */
1502};
1503
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001504#define FUTURE_COMMON_GETSETLIST \
1505 {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
1506 {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
1507 (setter)FutureObj_set_blocking, NULL}, \
1508 {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
1509 {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
1510 {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
1511 {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00001512 {"_log_traceback", (getter)FutureObj_get_log_traceback, \
1513 (setter)FutureObj_set_log_traceback, NULL}, \
Chris Jerdonek1ce58412020-05-15 16:55:50 -07001514 {"_source_traceback", (getter)FutureObj_get_source_traceback, \
1515 NULL, NULL}, \
1516 {"_cancel_message", (getter)FutureObj_get_cancel_message, \
1517 (setter)FutureObj_set_cancel_message, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001518
1519static PyGetSetDef FutureType_getsetlist[] = {
1520 FUTURE_COMMON_GETSETLIST
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001521 {NULL} /* Sentinel */
1522};
1523
1524static void FutureObj_dealloc(PyObject *self);
1525
1526static PyTypeObject FutureType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001527 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001528 "_asyncio.Future",
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001529 sizeof(FutureObj), /* tp_basicsize */
1530 .tp_dealloc = FutureObj_dealloc,
1531 .tp_as_async = &FutureType_as_async,
1532 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02001533 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001534 .tp_doc = _asyncio_Future___init____doc__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001535 .tp_traverse = (traverseproc)FutureObj_traverse,
1536 .tp_clear = (inquiry)FutureObj_clear,
1537 .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001538 .tp_iter = (getiterfunc)future_new_iter,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001539 .tp_methods = FutureType_methods,
1540 .tp_getset = FutureType_getsetlist,
1541 .tp_dictoffset = offsetof(FutureObj, dict),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001542 .tp_init = (initproc)_asyncio_Future___init__,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001543 .tp_new = PyType_GenericNew,
1544 .tp_finalize = (destructor)FutureObj_finalize,
1545};
1546
1547static void
1548FutureObj_dealloc(PyObject *self)
1549{
1550 FutureObj *fut = (FutureObj *)self;
1551
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001552 if (Future_CheckExact(fut)) {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001553 /* When fut is subclass of Future, finalizer is called from
1554 * subtype_dealloc.
1555 */
1556 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1557 // resurrected.
1558 return;
1559 }
1560 }
1561
Alexander Mohrde34cbe2017-08-01 23:31:07 -07001562 PyObject_GC_UnTrack(self);
1563
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001564 if (fut->fut_weakreflist != NULL) {
1565 PyObject_ClearWeakRefs(self);
1566 }
1567
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001568 (void)FutureObj_clear(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001569 Py_TYPE(fut)->tp_free(fut);
1570}
1571
1572
1573/*********************** Future Iterator **************************/
1574
1575typedef struct {
1576 PyObject_HEAD
1577 FutureObj *future;
1578} futureiterobject;
1579
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001580
1581#define FI_FREELIST_MAXLEN 255
1582static futureiterobject *fi_freelist = NULL;
1583static Py_ssize_t fi_freelist_len = 0;
1584
1585
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001586static void
1587FutureIter_dealloc(futureiterobject *it)
1588{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001589 PyObject_GC_UnTrack(it);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001590 Py_CLEAR(it->future);
1591
1592 if (fi_freelist_len < FI_FREELIST_MAXLEN) {
1593 fi_freelist_len++;
1594 it->future = (FutureObj*) fi_freelist;
1595 fi_freelist = it;
1596 }
1597 else {
1598 PyObject_GC_Del(it);
1599 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001600}
1601
1602static PyObject *
1603FutureIter_iternext(futureiterobject *it)
1604{
1605 PyObject *res;
1606 FutureObj *fut = it->future;
1607
1608 if (fut == NULL) {
1609 return NULL;
1610 }
1611
1612 if (fut->fut_state == STATE_PENDING) {
1613 if (!fut->fut_blocking) {
1614 fut->fut_blocking = 1;
1615 Py_INCREF(fut);
1616 return (PyObject *)fut;
1617 }
Yury Selivanov0cf16f92017-12-25 10:48:15 -05001618 PyErr_SetString(PyExc_RuntimeError,
1619 "await wasn't used with future");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001620 return NULL;
1621 }
1622
Serhiy Storchakabca49392017-09-03 08:10:14 +03001623 it->future = NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001624 res = _asyncio_Future_result_impl(fut);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001625 if (res != NULL) {
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001626 /* The result of the Future is not an exception. */
Serhiy Storchakabca49392017-09-03 08:10:14 +03001627 (void)_PyGen_SetStopIterationValue(res);
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001628 Py_DECREF(res);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001629 }
1630
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001631 Py_DECREF(fut);
1632 return NULL;
1633}
1634
1635static PyObject *
INADA Naoki74c17532016-10-25 19:00:45 +09001636FutureIter_send(futureiterobject *self, PyObject *unused)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001637{
INADA Naoki74c17532016-10-25 19:00:45 +09001638 /* Future.__iter__ doesn't care about values that are pushed to the
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03001639 * generator, it just returns self.result().
INADA Naoki74c17532016-10-25 19:00:45 +09001640 */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001641 return FutureIter_iternext(self);
1642}
1643
1644static PyObject *
1645FutureIter_throw(futureiterobject *self, PyObject *args)
1646{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001647 PyObject *type, *val = NULL, *tb = NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001648 if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1649 return NULL;
1650
1651 if (val == Py_None) {
1652 val = NULL;
1653 }
1654 if (tb == Py_None) {
1655 tb = NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001656 } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1657 PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1658 return NULL;
1659 }
1660
1661 Py_INCREF(type);
1662 Py_XINCREF(val);
1663 Py_XINCREF(tb);
1664
1665 if (PyExceptionClass_Check(type)) {
1666 PyErr_NormalizeException(&type, &val, &tb);
Yury Selivanovedfe8862016-12-01 11:37:47 -05001667 /* No need to call PyException_SetTraceback since we'll be calling
1668 PyErr_Restore for `type`, `val`, and `tb`. */
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001669 } else if (PyExceptionInstance_Check(type)) {
1670 if (val) {
1671 PyErr_SetString(PyExc_TypeError,
1672 "instance exception may not have a separate value");
1673 goto fail;
1674 }
1675 val = type;
1676 type = PyExceptionInstance_Class(type);
1677 Py_INCREF(type);
1678 if (tb == NULL)
1679 tb = PyException_GetTraceback(val);
1680 } else {
1681 PyErr_SetString(PyExc_TypeError,
1682 "exceptions must be classes deriving BaseException or "
1683 "instances of such a class");
1684 goto fail;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001685 }
1686
1687 Py_CLEAR(self->future);
1688
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001689 PyErr_Restore(type, val, tb);
1690
Serhiy Storchakabca49392017-09-03 08:10:14 +03001691 return NULL;
Benjamin Peterson996fc1f2016-11-14 00:15:44 -08001692
1693 fail:
1694 Py_DECREF(type);
1695 Py_XDECREF(val);
1696 Py_XDECREF(tb);
1697 return NULL;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001698}
1699
1700static PyObject *
1701FutureIter_close(futureiterobject *self, PyObject *arg)
1702{
1703 Py_CLEAR(self->future);
1704 Py_RETURN_NONE;
1705}
1706
1707static int
1708FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1709{
1710 Py_VISIT(it->future);
1711 return 0;
1712}
1713
1714static PyMethodDef FutureIter_methods[] = {
1715 {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1716 {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1717 {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1718 {NULL, NULL} /* Sentinel */
1719};
1720
1721static PyTypeObject FutureIterType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001722 PyVarObject_HEAD_INIT(NULL, 0)
INADA Naoki9f2ce252016-10-15 15:39:19 +09001723 "_asyncio.FutureIter",
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001724 .tp_basicsize = sizeof(futureiterobject),
1725 .tp_itemsize = 0,
1726 .tp_dealloc = (destructor)FutureIter_dealloc,
1727 .tp_getattro = PyObject_GenericGetAttr,
1728 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1729 .tp_traverse = (traverseproc)FutureIter_traverse,
1730 .tp_iter = PyObject_SelfIter,
1731 .tp_iternext = (iternextfunc)FutureIter_iternext,
1732 .tp_methods = FutureIter_methods,
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001733};
1734
1735static PyObject *
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001736future_new_iter(PyObject *fut)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001737{
1738 futureiterobject *it;
1739
1740 if (!PyObject_TypeCheck(fut, &FutureType)) {
1741 PyErr_BadInternalCall();
1742 return NULL;
1743 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001744
1745 ENSURE_FUTURE_ALIVE(fut)
1746
1747 if (fi_freelist_len) {
1748 fi_freelist_len--;
1749 it = fi_freelist;
1750 fi_freelist = (futureiterobject*) it->future;
1751 it->future = NULL;
1752 _Py_NewReference((PyObject*) it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001753 }
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05001754 else {
1755 it = PyObject_GC_New(futureiterobject, &FutureIterType);
1756 if (it == NULL) {
1757 return NULL;
1758 }
1759 }
1760
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001761 Py_INCREF(fut);
1762 it->future = (FutureObj*)fut;
INADA Naoki1be427b2016-10-11 02:12:34 +09001763 PyObject_GC_Track(it);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001764 return (PyObject*)it;
1765}
1766
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001767
1768/*********************** Task **************************/
1769
1770
1771/*[clinic input]
1772class _asyncio.Task "TaskObj *" "&Task_Type"
1773[clinic start generated code]*/
1774/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1775
1776static int task_call_step_soon(TaskObj *, PyObject *);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001777static PyObject * task_wakeup(TaskObj *, PyObject *);
1778static PyObject * task_step(TaskObj *, PyObject *);
1779
1780/* ----- Task._step wrapper */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001781
INADA Naokic411a7d2016-10-18 11:48:14 +09001782static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001783TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001784{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001785 Py_CLEAR(o->sw_task);
1786 Py_CLEAR(o->sw_arg);
1787 return 0;
1788}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09001789
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001790static void
Serhiy Storchakabca49392017-09-03 08:10:14 +03001791TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001792{
1793 PyObject_GC_UnTrack(o);
Serhiy Storchakabca49392017-09-03 08:10:14 +03001794 (void)TaskStepMethWrapper_clear(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001795 Py_TYPE(o)->tp_free(o);
1796}
1797
1798static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001799TaskStepMethWrapper_call(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001800 PyObject *args, PyObject *kwds)
1801{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001802 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1803 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1804 return NULL;
1805 }
1806 if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
1807 PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
1808 return NULL;
1809 }
Yury Selivanov22feeb82018-01-24 11:31:01 -05001810 return task_step(o->sw_task, o->sw_arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001811}
1812
1813static int
Serhiy Storchakabca49392017-09-03 08:10:14 +03001814TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001815 visitproc visit, void *arg)
1816{
1817 Py_VISIT(o->sw_task);
1818 Py_VISIT(o->sw_arg);
1819 return 0;
1820}
1821
1822static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001823TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001824{
1825 if (o->sw_task) {
1826 Py_INCREF(o->sw_task);
1827 return (PyObject*)o->sw_task;
1828 }
1829 Py_RETURN_NONE;
1830}
1831
Serhiy Storchakabca49392017-09-03 08:10:14 +03001832static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
1833 {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001834 {NULL} /* Sentinel */
1835};
1836
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001837static PyTypeObject TaskStepMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001838 PyVarObject_HEAD_INIT(NULL, 0)
Serhiy Storchakabca49392017-09-03 08:10:14 +03001839 "TaskStepMethWrapper",
1840 .tp_basicsize = sizeof(TaskStepMethWrapper),
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001841 .tp_itemsize = 0,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001842 .tp_getset = TaskStepMethWrapper_getsetlist,
1843 .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
1844 .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001845 .tp_getattro = PyObject_GenericGetAttr,
1846 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Serhiy Storchakabca49392017-09-03 08:10:14 +03001847 .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
1848 .tp_clear = (inquiry)TaskStepMethWrapper_clear,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001849};
1850
1851static PyObject *
Serhiy Storchakabca49392017-09-03 08:10:14 +03001852TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001853{
Serhiy Storchakabca49392017-09-03 08:10:14 +03001854 TaskStepMethWrapper *o;
1855 o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001856 if (o == NULL) {
1857 return NULL;
1858 }
1859
1860 Py_INCREF(task);
1861 o->sw_task = task;
1862
1863 Py_XINCREF(arg);
1864 o->sw_arg = arg;
1865
1866 PyObject_GC_Track(o);
1867 return (PyObject*) o;
1868}
1869
1870/* ----- Task._wakeup wrapper */
1871
1872static PyObject *
1873TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1874 PyObject *args, PyObject *kwds)
1875{
1876 PyObject *fut;
1877
Serhiy Storchakabca49392017-09-03 08:10:14 +03001878 if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
1879 PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
1880 return NULL;
1881 }
1882 if (!PyArg_ParseTuple(args, "O", &fut)) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001883 return NULL;
1884 }
1885
Yury Selivanov22feeb82018-01-24 11:31:01 -05001886 return task_wakeup(o->ww_task, fut);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001887}
1888
1889static int
1890TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1891{
1892 Py_CLEAR(o->ww_task);
1893 return 0;
1894}
1895
1896static int
1897TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1898 visitproc visit, void *arg)
1899{
1900 Py_VISIT(o->ww_task);
1901 return 0;
1902}
1903
1904static void
1905TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1906{
1907 PyObject_GC_UnTrack(o);
1908 (void)TaskWakeupMethWrapper_clear(o);
1909 Py_TYPE(o)->tp_free(o);
1910}
1911
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001912static PyObject *
1913TaskWakeupMethWrapper_get___self__(TaskWakeupMethWrapper *o, void *Py_UNUSED(ignored))
1914{
1915 if (o->ww_task) {
1916 Py_INCREF(o->ww_task);
1917 return (PyObject*)o->ww_task;
1918 }
1919 Py_RETURN_NONE;
1920}
1921
1922static PyGetSetDef TaskWakeupMethWrapper_getsetlist[] = {
1923 {"__self__", (getter)TaskWakeupMethWrapper_get___self__, NULL, NULL},
1924 {NULL} /* Sentinel */
1925};
1926
Benjamin Peterson3c8aae92018-07-05 22:39:34 -07001927static PyTypeObject TaskWakeupMethWrapper_Type = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02001928 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001929 "TaskWakeupMethWrapper",
1930 .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1931 .tp_itemsize = 0,
1932 .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1933 .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1934 .tp_getattro = PyObject_GenericGetAttr,
1935 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1936 .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1937 .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02001938 .tp_getset = TaskWakeupMethWrapper_getsetlist,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04001939};
1940
1941static PyObject *
1942TaskWakeupMethWrapper_new(TaskObj *task)
1943{
1944 TaskWakeupMethWrapper *o;
1945 o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1946 if (o == NULL) {
1947 return NULL;
1948 }
1949
1950 Py_INCREF(task);
1951 o->ww_task = task;
1952
1953 PyObject_GC_Track(o);
1954 return (PyObject*) o;
1955}
1956
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001957/* ----- Task introspection helpers */
1958
1959static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001960register_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001961{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001962 _Py_IDENTIFIER(add);
1963
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001964 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1965 &PyId_add, task);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001966 if (res == NULL) {
1967 return -1;
1968 }
1969 Py_DECREF(res);
1970 return 0;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001971}
1972
1973
1974static int
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001975unregister_task(PyObject *task)
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001976{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05001977 _Py_IDENTIFIER(discard);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001978
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02001979 PyObject *res = _PyObject_CallMethodIdOneArg(all_tasks,
1980 &PyId_discard, task);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02001981 if (res == NULL) {
1982 return -1;
1983 }
1984 Py_DECREF(res);
1985 return 0;
1986}
1987
1988
1989static int
1990enter_task(PyObject *loop, PyObject *task)
1991{
1992 PyObject *item;
1993 Py_hash_t hash;
1994 hash = PyObject_Hash(loop);
1995 if (hash == -1) {
1996 return -1;
1997 }
1998 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
1999 if (item != NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002000 Py_INCREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002001 PyErr_Format(
2002 PyExc_RuntimeError,
2003 "Cannot enter into task %R while another " \
2004 "task %R is being executed.",
2005 task, item, NULL);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002006 Py_DECREF(item);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002007 return -1;
2008 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03002009 if (PyErr_Occurred()) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002010 return -1;
2011 }
Serhiy Storchaka66553542018-05-20 16:30:31 +03002012 return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002013}
2014
2015
2016static int
2017leave_task(PyObject *loop, PyObject *task)
2018/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
2019{
2020 PyObject *item;
2021 Py_hash_t hash;
2022 hash = PyObject_Hash(loop);
2023 if (hash == -1) {
2024 return -1;
2025 }
2026 item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash);
2027 if (item != task) {
2028 if (item == NULL) {
2029 /* Not entered, replace with None */
2030 item = Py_None;
2031 }
2032 PyErr_Format(
2033 PyExc_RuntimeError,
2034 "Leaving task %R does not match the current task %R.",
2035 task, item, NULL);
2036 return -1;
2037 }
2038 return _PyDict_DelItem_KnownHash(current_tasks, loop, hash);
2039}
2040
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002041/* ----- Task */
2042
2043/*[clinic input]
2044_asyncio.Task.__init__
2045
Serhiy Storchakabca49392017-09-03 08:10:14 +03002046 coro: object
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002047 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002048 loop: object = None
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002049 name: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002050
2051A coroutine wrapped in a Future.
2052[clinic start generated code]*/
2053
2054static int
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002055_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
2056 PyObject *name)
2057/*[clinic end generated code: output=88b12b83d570df50 input=352a3137fe60091d]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002058{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002059 if (future_init((FutureObj*)self, loop)) {
INADA Naokic411a7d2016-10-18 11:48:14 +09002060 return -1;
2061 }
INADA Naokic411a7d2016-10-18 11:48:14 +09002062
Yury Selivanova9d7e552017-12-19 07:18:45 -05002063 int is_coro = is_coroutine(coro);
2064 if (is_coro == -1) {
2065 return -1;
2066 }
2067 if (is_coro == 0) {
2068 self->task_log_destroy_pending = 0;
2069 PyErr_Format(PyExc_TypeError,
2070 "a coroutine was expected, got %R",
2071 coro, NULL);
2072 return -1;
Andrew Svetlovf74ef452017-12-15 07:04:38 +02002073 }
2074
Oren Milmand019bc82018-02-13 12:28:33 +02002075 Py_XSETREF(self->task_context, PyContext_CopyCurrent());
Yury Selivanovf23746a2018-01-22 19:11:18 -05002076 if (self->task_context == NULL) {
2077 return -1;
2078 }
2079
Oren Milmand019bc82018-02-13 12:28:33 +02002080 Py_CLEAR(self->task_fut_waiter);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002081 self->task_must_cancel = 0;
2082 self->task_log_destroy_pending = 1;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002083 Py_INCREF(coro);
Oren Milmand019bc82018-02-13 12:28:33 +02002084 Py_XSETREF(self->task_coro, coro);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002085
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002086 if (name == Py_None) {
2087 name = PyUnicode_FromFormat("Task-%" PRIu64, ++task_name_counter);
Alex Grönholma7548232018-08-09 23:49:49 +03002088 } else if (!PyUnicode_CheckExact(name)) {
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002089 name = PyObject_Str(name);
2090 } else {
2091 Py_INCREF(name);
2092 }
2093 Py_XSETREF(self->task_name, name);
2094 if (self->task_name == NULL) {
2095 return -1;
2096 }
2097
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002098 if (task_call_step_soon(self, NULL)) {
2099 return -1;
INADA Naokic411a7d2016-10-18 11:48:14 +09002100 }
Yury Selivanovca9b36c2017-12-23 15:04:15 -05002101 return register_task((PyObject*)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002102}
2103
2104static int
2105TaskObj_clear(TaskObj *task)
2106{
2107 (void)FutureObj_clear((FutureObj*) task);
Yury Selivanovf23746a2018-01-22 19:11:18 -05002108 Py_CLEAR(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002109 Py_CLEAR(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002110 Py_CLEAR(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002111 Py_CLEAR(task->task_fut_waiter);
2112 return 0;
2113}
2114
2115static int
2116TaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
2117{
Yury Selivanovf23746a2018-01-22 19:11:18 -05002118 Py_VISIT(task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002119 Py_VISIT(task->task_coro);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002120 Py_VISIT(task->task_name);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002121 Py_VISIT(task->task_fut_waiter);
2122 (void)FutureObj_traverse((FutureObj*) task, visit, arg);
2123 return 0;
2124}
2125
2126static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002127TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002128{
2129 if (task->task_log_destroy_pending) {
2130 Py_RETURN_TRUE;
2131 }
2132 else {
2133 Py_RETURN_FALSE;
2134 }
2135}
2136
2137static int
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002138TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002139{
Zackery Spytz842acaa2018-12-17 07:52:45 -07002140 if (val == NULL) {
2141 PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
2142 return -1;
2143 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002144 int is_true = PyObject_IsTrue(val);
2145 if (is_true < 0) {
2146 return -1;
2147 }
2148 task->task_log_destroy_pending = is_true;
2149 return 0;
2150}
2151
2152static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002153TaskObj_get_must_cancel(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002154{
2155 if (task->task_must_cancel) {
2156 Py_RETURN_TRUE;
2157 }
2158 else {
2159 Py_RETURN_FALSE;
2160 }
2161}
2162
2163static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002164TaskObj_get_coro(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002165{
2166 if (task->task_coro) {
2167 Py_INCREF(task->task_coro);
2168 return task->task_coro;
2169 }
2170
2171 Py_RETURN_NONE;
2172}
2173
2174static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002175TaskObj_get_fut_waiter(TaskObj *task, void *Py_UNUSED(ignored))
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002176{
2177 if (task->task_fut_waiter) {
2178 Py_INCREF(task->task_fut_waiter);
2179 return task->task_fut_waiter;
2180 }
2181
2182 Py_RETURN_NONE;
2183}
2184
2185/*[clinic input]
2186@classmethod
2187_asyncio.Task.current_task
2188
Serhiy Storchakabca49392017-09-03 08:10:14 +03002189 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002190
2191Return the currently running task in an event loop or None.
2192
2193By default the current task for the current event loop is returned.
2194
2195None is returned when called not in the context of a Task.
2196[clinic start generated code]*/
2197
2198static PyObject *
2199_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002200/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002201{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002202 PyObject *ret;
2203 PyObject *current_task_func;
2204
Inada Naokic5c6cda2019-03-22 20:07:32 +09002205 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002206 "Task.current_task() is deprecated, " \
2207 "use asyncio.current_task() instead",
2208 1) < 0) {
2209 return NULL;
2210 }
2211
2212 current_task_func = _PyObject_GetAttrId(asyncio_mod, &PyId_current_task);
2213 if (current_task_func == NULL) {
2214 return NULL;
2215 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002216
Yury Selivanov8d26aa92017-03-02 22:16:33 -05002217 if (loop == Py_None) {
Yury Selivanova70232f2017-12-13 14:49:42 -05002218 loop = get_event_loop();
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002219 if (loop == NULL) {
Serhiy Storchaka66553542018-05-20 16:30:31 +03002220 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002221 return NULL;
2222 }
Petr Viktorinffd97532020-02-11 17:46:57 +01002223 ret = PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002224 Py_DECREF(current_task_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002225 Py_DECREF(loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002226 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002227 }
2228 else {
Petr Viktorinffd97532020-02-11 17:46:57 +01002229 ret = PyObject_CallOneArg(current_task_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002230 Py_DECREF(current_task_func);
2231 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002232 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002233}
2234
2235/*[clinic input]
2236@classmethod
2237_asyncio.Task.all_tasks
2238
Serhiy Storchakabca49392017-09-03 08:10:14 +03002239 loop: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002240
2241Return a set of all tasks for an event loop.
2242
2243By default all tasks for the current event loop are returned.
2244[clinic start generated code]*/
2245
2246static PyObject *
2247_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002248/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002249{
2250 PyObject *res;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002251 PyObject *all_tasks_func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002252
Inada Naokic5c6cda2019-03-22 20:07:32 +09002253 if (PyErr_WarnEx(PyExc_DeprecationWarning,
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002254 "Task.all_tasks() is deprecated, " \
2255 "use asyncio.all_tasks() instead",
2256 1) < 0) {
2257 return NULL;
2258 }
2259
Yury Selivanov416c1eb2018-05-28 17:54:02 -04002260 all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
Serhiy Storchaka66553542018-05-20 16:30:31 +03002261 if (all_tasks_func == NULL) {
2262 return NULL;
2263 }
2264
Petr Viktorinffd97532020-02-11 17:46:57 +01002265 res = PyObject_CallOneArg(all_tasks_func, loop);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02002266 Py_DECREF(all_tasks_func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002267 return res;
2268}
2269
2270/*[clinic input]
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002271_asyncio.Task._make_cancelled_error
2272
2273Create the CancelledError to raise if the Task is cancelled.
2274
2275This should only be called once when handling a cancellation since
2276it erases the context exception value.
2277[clinic start generated code]*/
2278
2279static PyObject *
2280_asyncio_Task__make_cancelled_error_impl(TaskObj *self)
2281/*[clinic end generated code: output=55a819e8b4276fab input=52c0e32de8e2f840]*/
2282{
2283 FutureObj *fut = (FutureObj*)self;
2284 return _asyncio_Future__make_cancelled_error_impl(fut);
2285}
2286
2287
2288/*[clinic input]
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002289_asyncio.Task._repr_info
2290[clinic start generated code]*/
2291
2292static PyObject *
2293_asyncio_Task__repr_info_impl(TaskObj *self)
2294/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
2295{
Petr Viktorinffd97532020-02-11 17:46:57 +01002296 return PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002297}
2298
2299/*[clinic input]
2300_asyncio.Task.cancel
2301
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002302 msg: object = None
2303
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002304Request that this task cancel itself.
2305
2306This arranges for a CancelledError to be thrown into the
2307wrapped coroutine on the next cycle through the event loop.
2308The coroutine then has a chance to clean up or even deny
2309the request using try/except/finally.
2310
2311Unlike Future.cancel, this does not guarantee that the
2312task will be cancelled: the exception might be caught and
2313acted upon, delaying cancellation of the task or preventing
2314cancellation completely. The task may also return a value or
2315raise a different exception.
2316
2317Immediately after this method is called, Task.cancelled() will
2318not return True (unless the task was already cancelled). A
2319task will be marked as cancelled when the wrapped coroutine
2320terminates with a CancelledError exception (even if cancel()
2321was not called).
2322[clinic start generated code]*/
2323
2324static PyObject *
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002325_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
2326/*[clinic end generated code: output=c66b60d41c74f9f1 input=f4ff8e8ffc5f1c00]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002327{
Yury Selivanov7ce1c6f2017-06-11 13:49:18 +00002328 self->task_log_tb = 0;
2329
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002330 if (self->task_state != STATE_PENDING) {
2331 Py_RETURN_FALSE;
2332 }
2333
2334 if (self->task_fut_waiter) {
2335 PyObject *res;
2336 int is_true;
2337
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002338 res = _PyObject_CallMethodIdOneArg(self->task_fut_waiter,
2339 &PyId_cancel, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002340 if (res == NULL) {
2341 return NULL;
2342 }
2343
2344 is_true = PyObject_IsTrue(res);
2345 Py_DECREF(res);
2346 if (is_true < 0) {
2347 return NULL;
2348 }
2349
2350 if (is_true) {
2351 Py_RETURN_TRUE;
2352 }
2353 }
2354
2355 self->task_must_cancel = 1;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002356 Py_XINCREF(msg);
2357 Py_XSETREF(self->task_cancel_msg, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002358 Py_RETURN_TRUE;
2359}
2360
2361/*[clinic input]
2362_asyncio.Task.get_stack
2363
2364 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002365 limit: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002366
2367Return the list of stack frames for this task's coroutine.
2368
2369If the coroutine is not done, this returns the stack where it is
2370suspended. If the coroutine has completed successfully or was
2371cancelled, this returns an empty list. If the coroutine was
2372terminated by an exception, this returns the list of traceback
2373frames.
2374
2375The frames are always ordered from oldest to newest.
2376
2377The optional limit gives the maximum number of frames to
2378return; by default all available frames are returned. Its
2379meaning differs depending on whether a stack or a traceback is
2380returned: the newest frames of a stack are returned, but the
2381oldest frames of a traceback are returned. (This matches the
2382behavior of the traceback module.)
2383
2384For reasons beyond our control, only one stack frame is
2385returned for a suspended coroutine.
2386[clinic start generated code]*/
2387
2388static PyObject *
2389_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002390/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002391{
2392 return PyObject_CallFunctionObjArgs(
2393 asyncio_task_get_stack_func, self, limit, NULL);
2394}
2395
2396/*[clinic input]
2397_asyncio.Task.print_stack
2398
2399 *
Serhiy Storchakabca49392017-09-03 08:10:14 +03002400 limit: object = None
2401 file: object = None
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002402
2403Print the stack or traceback for this task's coroutine.
2404
2405This produces output similar to that of the traceback module,
2406for the frames retrieved by get_stack(). The limit argument
2407is passed to get_stack(). The file argument is an I/O stream
2408to which the output is written; by default output is written
2409to sys.stderr.
2410[clinic start generated code]*/
2411
2412static PyObject *
2413_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
2414 PyObject *file)
Serhiy Storchakabca49392017-09-03 08:10:14 +03002415/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002416{
2417 return PyObject_CallFunctionObjArgs(
2418 asyncio_task_print_stack_func, self, limit, file, NULL);
2419}
2420
2421/*[clinic input]
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002422_asyncio.Task.set_result
2423
2424 result: object
2425 /
2426[clinic start generated code]*/
2427
2428static PyObject *
2429_asyncio_Task_set_result(TaskObj *self, PyObject *result)
2430/*[clinic end generated code: output=1dcae308bfcba318 input=9d1a00c07be41bab]*/
2431{
2432 PyErr_SetString(PyExc_RuntimeError,
2433 "Task does not support set_result operation");
2434 return NULL;
2435}
2436
2437/*[clinic input]
2438_asyncio.Task.set_exception
2439
2440 exception: object
2441 /
2442[clinic start generated code]*/
2443
2444static PyObject *
2445_asyncio_Task_set_exception(TaskObj *self, PyObject *exception)
2446/*[clinic end generated code: output=bc377fc28067303d input=9a8f65c83dcf893a]*/
2447{
2448 PyErr_SetString(PyExc_RuntimeError,
Andrew Svetlovfc359322017-12-30 15:40:27 +02002449 "Task does not support set_exception operation");
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002450 return NULL;
2451}
2452
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002453/*[clinic input]
Alex Grönholm98ef9202019-05-30 18:30:09 +03002454_asyncio.Task.get_coro
2455[clinic start generated code]*/
2456
2457static PyObject *
2458_asyncio_Task_get_coro_impl(TaskObj *self)
2459/*[clinic end generated code: output=bcac27c8cc6c8073 input=d2e8606c42a7b403]*/
2460{
2461 Py_INCREF(self->task_coro);
2462 return self->task_coro;
2463}
2464
2465/*[clinic input]
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002466_asyncio.Task.get_name
2467[clinic start generated code]*/
2468
2469static PyObject *
2470_asyncio_Task_get_name_impl(TaskObj *self)
2471/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
2472{
2473 if (self->task_name) {
2474 Py_INCREF(self->task_name);
2475 return self->task_name;
2476 }
2477
2478 Py_RETURN_NONE;
2479}
2480
2481/*[clinic input]
2482_asyncio.Task.set_name
2483
2484 value: object
2485 /
2486[clinic start generated code]*/
2487
2488static PyObject *
2489_asyncio_Task_set_name(TaskObj *self, PyObject *value)
2490/*[clinic end generated code: output=138a8d51e32057d6 input=a8359b6e65f8fd31]*/
2491{
Alex Grönholma7548232018-08-09 23:49:49 +03002492 if (!PyUnicode_CheckExact(value)) {
2493 value = PyObject_Str(value);
2494 if (value == NULL) {
2495 return NULL;
2496 }
2497 } else {
2498 Py_INCREF(value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002499 }
2500
Alex Grönholma7548232018-08-09 23:49:49 +03002501 Py_XSETREF(self->task_name, value);
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002502 Py_RETURN_NONE;
2503}
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002504
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002505static void
2506TaskObj_finalize(TaskObj *task)
2507{
2508 _Py_IDENTIFIER(call_exception_handler);
2509 _Py_IDENTIFIER(task);
2510 _Py_IDENTIFIER(message);
2511 _Py_IDENTIFIER(source_traceback);
2512
Serhiy Storchakabca49392017-09-03 08:10:14 +03002513 PyObject *context;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002514 PyObject *message = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002515 PyObject *func;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002516 PyObject *error_type, *error_value, *error_traceback;
2517
2518 if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
2519 goto done;
2520 }
2521
2522 /* Save the current exception, if any. */
2523 PyErr_Fetch(&error_type, &error_value, &error_traceback);
2524
2525 context = PyDict_New();
2526 if (context == NULL) {
2527 goto finally;
2528 }
2529
2530 message = PyUnicode_FromString("Task was destroyed but it is pending!");
2531 if (message == NULL) {
2532 goto finally;
2533 }
2534
2535 if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
2536 _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
2537 {
2538 goto finally;
2539 }
2540
2541 if (task->task_source_tb != NULL) {
2542 if (_PyDict_SetItemId(context, &PyId_source_traceback,
2543 task->task_source_tb) < 0)
2544 {
2545 goto finally;
2546 }
2547 }
2548
2549 func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
2550 if (func != NULL) {
Petr Viktorinffd97532020-02-11 17:46:57 +01002551 PyObject *res = PyObject_CallOneArg(func, context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002552 if (res == NULL) {
2553 PyErr_WriteUnraisable(func);
2554 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002555 else {
2556 Py_DECREF(res);
2557 }
2558 Py_DECREF(func);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002559 }
2560
2561finally:
Serhiy Storchakabca49392017-09-03 08:10:14 +03002562 Py_XDECREF(context);
2563 Py_XDECREF(message);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002564
2565 /* Restore the saved exception. */
2566 PyErr_Restore(error_type, error_value, error_traceback);
2567
2568done:
2569 FutureObj_finalize((FutureObj*)task);
2570}
2571
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002572static PyObject *
2573task_cls_getitem(PyObject *cls, PyObject *type)
2574{
2575 Py_INCREF(cls);
2576 return cls;
2577}
2578
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002579static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
2580
2581static PyMethodDef TaskType_methods[] = {
2582 _ASYNCIO_FUTURE_RESULT_METHODDEF
2583 _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002584 _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
2585 _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
2586 _ASYNCIO_FUTURE_CANCELLED_METHODDEF
2587 _ASYNCIO_FUTURE_DONE_METHODDEF
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002588 _ASYNCIO_TASK_SET_RESULT_METHODDEF
2589 _ASYNCIO_TASK_SET_EXCEPTION_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002590 _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
2591 _ASYNCIO_TASK_ALL_TASKS_METHODDEF
2592 _ASYNCIO_TASK_CANCEL_METHODDEF
2593 _ASYNCIO_TASK_GET_STACK_METHODDEF
2594 _ASYNCIO_TASK_PRINT_STACK_METHODDEF
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002595 _ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002596 _ASYNCIO_TASK__REPR_INFO_METHODDEF
Alex Grönholmcca4eec2018-08-09 00:06:47 +03002597 _ASYNCIO_TASK_GET_NAME_METHODDEF
2598 _ASYNCIO_TASK_SET_NAME_METHODDEF
Alex Grönholm98ef9202019-05-30 18:30:09 +03002599 _ASYNCIO_TASK_GET_CORO_METHODDEF
Batuhan TaÅŸkayadec36722019-12-07 14:05:07 +03002600 {"__class_getitem__", task_cls_getitem, METH_O|METH_CLASS, NULL},
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002601 {NULL, NULL} /* Sentinel */
2602};
2603
2604static PyGetSetDef TaskType_getsetlist[] = {
2605 FUTURE_COMMON_GETSETLIST
2606 {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
2607 (setter)TaskObj_set_log_destroy_pending, NULL},
2608 {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
2609 {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
2610 {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
2611 {NULL} /* Sentinel */
2612};
2613
2614static PyTypeObject TaskType = {
Victor Stinner1aea8fb2016-10-28 19:13:52 +02002615 PyVarObject_HEAD_INIT(NULL, 0)
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002616 "_asyncio.Task",
2617 sizeof(TaskObj), /* tp_basicsize */
2618 .tp_base = &FutureType,
2619 .tp_dealloc = TaskObj_dealloc,
2620 .tp_as_async = &FutureType_as_async,
2621 .tp_repr = (reprfunc)FutureObj_repr,
Antoine Pitrouada319b2019-05-29 22:12:38 +02002622 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002623 .tp_doc = _asyncio_Task___init____doc__,
2624 .tp_traverse = (traverseproc)TaskObj_traverse,
2625 .tp_clear = (inquiry)TaskObj_clear,
2626 .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
2627 .tp_iter = (getiterfunc)future_new_iter,
2628 .tp_methods = TaskType_methods,
2629 .tp_getset = TaskType_getsetlist,
2630 .tp_dictoffset = offsetof(TaskObj, dict),
2631 .tp_init = (initproc)_asyncio_Task___init__,
2632 .tp_new = PyType_GenericNew,
2633 .tp_finalize = (destructor)TaskObj_finalize,
2634};
2635
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002636static void
2637TaskObj_dealloc(PyObject *self)
2638{
2639 TaskObj *task = (TaskObj *)self;
2640
2641 if (Task_CheckExact(self)) {
2642 /* When fut is subclass of Task, finalizer is called from
2643 * subtype_dealloc.
2644 */
2645 if (PyObject_CallFinalizerFromDealloc(self) < 0) {
2646 // resurrected.
2647 return;
2648 }
2649 }
2650
Alexander Mohrde34cbe2017-08-01 23:31:07 -07002651 PyObject_GC_UnTrack(self);
2652
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002653 if (task->task_weakreflist != NULL) {
2654 PyObject_ClearWeakRefs(self);
2655 }
2656
2657 (void)TaskObj_clear(task);
2658 Py_TYPE(task)->tp_free(task);
2659}
2660
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002661static int
2662task_call_step_soon(TaskObj *task, PyObject *arg)
2663{
Serhiy Storchakabca49392017-09-03 08:10:14 +03002664 PyObject *cb = TaskStepMethWrapper_new(task, arg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002665 if (cb == NULL) {
2666 return -1;
2667 }
2668
Yury Selivanovf23746a2018-01-22 19:11:18 -05002669 int ret = call_soon(task->task_loop, cb, NULL, task->task_context);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002670 Py_DECREF(cb);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05002671 return ret;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002672}
2673
2674static PyObject *
2675task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
2676{
2677 PyObject* msg;
2678
2679 va_list vargs;
2680#ifdef HAVE_STDARG_PROTOTYPES
2681 va_start(vargs, format);
2682#else
2683 va_start(vargs);
2684#endif
2685 msg = PyUnicode_FromFormatV(format, vargs);
2686 va_end(vargs);
2687
2688 if (msg == NULL) {
2689 return NULL;
2690 }
2691
Petr Viktorinffd97532020-02-11 17:46:57 +01002692 PyObject *e = PyObject_CallOneArg(et, msg);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002693 Py_DECREF(msg);
2694 if (e == NULL) {
2695 return NULL;
2696 }
2697
2698 if (task_call_step_soon(task, e) == -1) {
2699 Py_DECREF(e);
2700 return NULL;
2701 }
2702
2703 Py_DECREF(e);
2704 Py_RETURN_NONE;
2705}
2706
2707static PyObject *
2708task_step_impl(TaskObj *task, PyObject *exc)
2709{
2710 int res;
2711 int clear_exc = 0;
2712 PyObject *result = NULL;
Serhiy Storchakabca49392017-09-03 08:10:14 +03002713 PyObject *coro;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002714 PyObject *o;
2715
2716 if (task->task_state != STATE_PENDING) {
Yury Selivanov0cf16f92017-12-25 10:48:15 -05002717 PyErr_Format(asyncio_InvalidStateError,
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002718 "_step(): already done: %R %R",
2719 task,
2720 exc ? exc : Py_None);
INADA Naokic411a7d2016-10-18 11:48:14 +09002721 goto fail;
2722 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09002723
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002724 if (task->task_must_cancel) {
2725 assert(exc != Py_None);
2726
2727 if (exc) {
2728 /* Check if exc is a CancelledError */
2729 res = PyObject_IsInstance(exc, asyncio_CancelledError);
2730 if (res == -1) {
2731 /* An error occurred, abort */
2732 goto fail;
2733 }
2734 if (res == 0) {
2735 /* exc is not CancelledError; reset it to NULL */
2736 exc = NULL;
2737 }
2738 }
2739
2740 if (!exc) {
2741 /* exc was not a CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002742 exc = create_cancelled_error(task->task_cancel_msg);
2743
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002744 if (!exc) {
2745 goto fail;
2746 }
2747 clear_exc = 1;
2748 }
2749
2750 task->task_must_cancel = 0;
2751 }
2752
2753 Py_CLEAR(task->task_fut_waiter);
2754
Serhiy Storchakabca49392017-09-03 08:10:14 +03002755 coro = task->task_coro;
2756 if (coro == NULL) {
2757 PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
Chris Jerdonekd2c349b2020-05-08 03:54:38 -07002758 if (clear_exc) {
2759 /* We created 'exc' during this call */
2760 Py_DECREF(exc);
2761 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03002762 return NULL;
2763 }
2764
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002765 if (exc == NULL) {
2766 if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
2767 result = _PyGen_Send((PyGenObject*)coro, Py_None);
2768 }
2769 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002770 result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002771 }
2772 }
2773 else {
Jeroen Demeyer59ad1102019-07-11 10:59:05 +02002774 result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002775 if (clear_exc) {
2776 /* We created 'exc' during this call */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002777 Py_DECREF(exc);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002778 }
2779 }
2780
2781 if (result == NULL) {
2782 PyObject *et, *ev, *tb;
2783
2784 if (_PyGen_FetchStopIterationValue(&o) == 0) {
2785 /* The error is StopIteration and that means that
2786 the underlying coroutine has resolved */
Yury Selivanovedad4d82019-09-25 03:32:08 -07002787
2788 PyObject *res;
INADA Naoki991adca2017-05-11 21:18:38 +09002789 if (task->task_must_cancel) {
2790 // Task is cancelled right before coro stops.
INADA Naoki991adca2017-05-11 21:18:38 +09002791 task->task_must_cancel = 0;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002792 res = future_cancel((FutureObj*)task, task->task_cancel_msg);
INADA Naoki991adca2017-05-11 21:18:38 +09002793 }
Yury Selivanovedad4d82019-09-25 03:32:08 -07002794 else {
2795 res = future_set_result((FutureObj*)task, o);
2796 }
2797
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002798 Py_DECREF(o);
Yury Selivanovedad4d82019-09-25 03:32:08 -07002799
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002800 if (res == NULL) {
2801 return NULL;
2802 }
2803 Py_DECREF(res);
2804 Py_RETURN_NONE;
2805 }
2806
2807 if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
2808 /* CancelledError */
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002809 PyErr_Fetch(&et, &ev, &tb);
2810
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002811 FutureObj *fut = (FutureObj*)task;
2812 _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
2813 exc_state->exc_type = et;
2814 exc_state->exc_value = ev;
2815 exc_state->exc_traceback = tb;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002816
Chris Jerdonekda742ba2020-05-17 22:47:31 -07002817 return future_cancel(fut, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002818 }
2819
2820 /* Some other exception; pop it and call Task.set_exception() */
2821 PyErr_Fetch(&et, &ev, &tb);
INADA Naoki991adca2017-05-11 21:18:38 +09002822
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002823 assert(et);
2824 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2825 PyErr_NormalizeException(&et, &ev, &tb);
2826 }
Yury Selivanovedfe8862016-12-01 11:37:47 -05002827 if (tb != NULL) {
2828 PyException_SetTraceback(ev, tb);
2829 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002830 o = future_set_exception((FutureObj*)task, ev);
2831 if (!o) {
2832 /* An exception in Task.set_exception() */
Serhiy Storchakabca49392017-09-03 08:10:14 +03002833 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002834 Py_XDECREF(tb);
2835 Py_XDECREF(ev);
2836 goto fail;
2837 }
2838 assert(o == Py_None);
Serhiy Storchakabca49392017-09-03 08:10:14 +03002839 Py_DECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002840
Yury Selivanov431b5402019-05-27 14:45:12 +02002841 if (PyErr_GivenExceptionMatches(et, PyExc_KeyboardInterrupt) ||
2842 PyErr_GivenExceptionMatches(et, PyExc_SystemExit))
2843 {
2844 /* We've got a KeyboardInterrupt or a SystemError; re-raise it */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002845 PyErr_Restore(et, ev, tb);
2846 goto fail;
2847 }
2848
Serhiy Storchakabca49392017-09-03 08:10:14 +03002849 Py_DECREF(et);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002850 Py_XDECREF(tb);
2851 Py_XDECREF(ev);
2852
2853 Py_RETURN_NONE;
2854 }
2855
2856 if (result == (PyObject*)task) {
2857 /* We have a task that wants to await on itself */
2858 goto self_await;
2859 }
2860
2861 /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2862 if (Future_CheckExact(result) || Task_CheckExact(result)) {
2863 PyObject *wrapper;
2864 PyObject *res;
2865 FutureObj *fut = (FutureObj*)result;
2866
2867 /* Check if `result` future is attached to a different loop */
2868 if (fut->fut_loop != task->task_loop) {
2869 goto different_loop;
2870 }
2871
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002872 if (!fut->fut_blocking) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002873 goto yield_insteadof_yf;
2874 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002875
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002876 fut->fut_blocking = 0;
2877
2878 /* result.add_done_callback(task._wakeup) */
2879 wrapper = TaskWakeupMethWrapper_new(task);
2880 if (wrapper == NULL) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002881 goto fail;
2882 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002883 res = future_add_done_callback(
2884 (FutureObj*)result, wrapper, task->task_context);
2885 Py_DECREF(wrapper);
2886 if (res == NULL) {
2887 goto fail;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002888 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002889 Py_DECREF(res);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002890
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002891 /* task._fut_waiter = result */
2892 task->task_fut_waiter = result; /* no incref is necessary */
2893
2894 if (task->task_must_cancel) {
2895 PyObject *r;
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002896 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002897 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2898 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002899 if (r == NULL) {
2900 return NULL;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002901 }
Elvis Pranskevichus0c797a62018-10-03 10:30:31 -04002902 is_true = PyObject_IsTrue(r);
2903 Py_DECREF(r);
2904 if (is_true < 0) {
2905 return NULL;
2906 }
2907 else if (is_true) {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002908 task->task_must_cancel = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002909 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002910 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002911
2912 Py_RETURN_NONE;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04002913 }
2914
2915 /* Check if `result` is None */
2916 if (result == Py_None) {
2917 /* Bare yield relinquishes control for one event loop iteration. */
2918 if (task_call_step_soon(task, NULL)) {
2919 goto fail;
2920 }
2921 return result;
2922 }
2923
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002924 /* Check if `result` is a Future-compatible object */
2925 if (_PyObject_LookupAttrId(result, &PyId__asyncio_future_blocking, &o) < 0) {
2926 goto fail;
2927 }
2928 if (o != NULL && o != Py_None) {
2929 /* `result` is a Future-compatible object */
2930 PyObject *wrapper;
2931 PyObject *res;
2932
2933 int blocking = PyObject_IsTrue(o);
2934 Py_DECREF(o);
2935 if (blocking < 0) {
2936 goto fail;
2937 }
2938
2939 /* Check if `result` future is attached to a different loop */
2940 PyObject *oloop = get_future_loop(result);
2941 if (oloop == NULL) {
2942 goto fail;
2943 }
2944 if (oloop != task->task_loop) {
2945 Py_DECREF(oloop);
2946 goto different_loop;
2947 }
2948 Py_DECREF(oloop);
2949
2950 if (!blocking) {
2951 goto yield_insteadof_yf;
2952 }
2953
2954 /* result._asyncio_future_blocking = False */
2955 if (_PyObject_SetAttrId(
2956 result, &PyId__asyncio_future_blocking, Py_False) == -1) {
2957 goto fail;
2958 }
2959
2960 wrapper = TaskWakeupMethWrapper_new(task);
2961 if (wrapper == NULL) {
2962 goto fail;
2963 }
2964
2965 /* result.add_done_callback(task._wakeup) */
2966 PyObject *add_cb = _PyObject_GetAttrId(
2967 result, &PyId_add_done_callback);
2968 if (add_cb == NULL) {
2969 Py_DECREF(wrapper);
2970 goto fail;
2971 }
2972 PyObject *stack[2];
2973 stack[0] = wrapper;
2974 stack[1] = (PyObject *)task->task_context;
Petr Viktorinffd97532020-02-11 17:46:57 +01002975 res = PyObject_Vectorcall(add_cb, stack, 1, context_kwname);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002976 Py_DECREF(add_cb);
2977 Py_DECREF(wrapper);
2978 if (res == NULL) {
2979 goto fail;
2980 }
2981 Py_DECREF(res);
2982
2983 /* task._fut_waiter = result */
2984 task->task_fut_waiter = result; /* no incref is necessary */
2985
2986 if (task->task_must_cancel) {
2987 PyObject *r;
2988 int is_true;
Chris Jerdonek1ce58412020-05-15 16:55:50 -07002989 r = _PyObject_CallMethodIdOneArg(result, &PyId_cancel,
2990 task->task_cancel_msg);
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03002991 if (r == NULL) {
2992 return NULL;
2993 }
2994 is_true = PyObject_IsTrue(r);
2995 Py_DECREF(r);
2996 if (is_true < 0) {
2997 return NULL;
2998 }
2999 else if (is_true) {
3000 task->task_must_cancel = 0;
3001 }
3002 }
3003
3004 Py_RETURN_NONE;
3005 }
3006
3007 Py_XDECREF(o);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003008 /* Check if `result` is a generator */
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003009 res = PyObject_IsInstance(result, (PyObject*)&PyGen_Type);
3010 if (res < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003011 goto fail;
3012 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003013 if (res) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003014 /* `result` is a generator */
Serhiy Storchaka66553542018-05-20 16:30:31 +03003015 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003016 task, PyExc_RuntimeError,
3017 "yield was used instead of yield from for "
Serhiy Storchaka66553542018-05-20 16:30:31 +03003018 "generator in task %R with %R", task, result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003019 Py_DECREF(result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03003020 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003021 }
3022
3023 /* The `result` is none of the above */
Serhiy Storchaka66553542018-05-20 16:30:31 +03003024 o = task_set_error_soon(
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003025 task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Serhiy Storchaka66553542018-05-20 16:30:31 +03003026 Py_DECREF(result);
3027 return o;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003028
3029self_await:
3030 o = task_set_error_soon(
3031 task, PyExc_RuntimeError,
3032 "Task cannot await on itself: %R", task);
3033 Py_DECREF(result);
3034 return o;
3035
3036yield_insteadof_yf:
3037 o = task_set_error_soon(
3038 task, PyExc_RuntimeError,
3039 "yield was used instead of yield from "
3040 "in task %R with %R",
3041 task, result);
3042 Py_DECREF(result);
3043 return o;
3044
3045different_loop:
3046 o = task_set_error_soon(
3047 task, PyExc_RuntimeError,
3048 "Task %R got Future %R attached to a different loop",
3049 task, result);
3050 Py_DECREF(result);
3051 return o;
3052
3053fail:
3054 Py_XDECREF(result);
3055 return NULL;
3056}
3057
3058static PyObject *
3059task_step(TaskObj *task, PyObject *exc)
3060{
3061 PyObject *res;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003062
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003063 if (enter_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003064 return NULL;
3065 }
3066
3067 res = task_step_impl(task, exc);
3068
3069 if (res == NULL) {
3070 PyObject *et, *ev, *tb;
3071 PyErr_Fetch(&et, &ev, &tb);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003072 leave_task(task->task_loop, (PyObject*)task);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003073 _PyErr_ChainExceptions(et, ev, tb);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003074 return NULL;
3075 }
3076 else {
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003077 if (leave_task(task->task_loop, (PyObject*)task) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003078 Py_DECREF(res);
3079 return NULL;
3080 }
3081 else {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003082 return res;
3083 }
3084 }
3085}
3086
3087static PyObject *
3088task_wakeup(TaskObj *task, PyObject *o)
3089{
Serhiy Storchakabca49392017-09-03 08:10:14 +03003090 PyObject *et, *ev, *tb;
3091 PyObject *result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003092 assert(o);
3093
3094 if (Future_CheckExact(o) || Task_CheckExact(o)) {
3095 PyObject *fut_result = NULL;
3096 int res = future_get_result((FutureObj*)o, &fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003097
3098 switch(res) {
3099 case -1:
3100 assert(fut_result == NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003101 break; /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003102 case 0:
3103 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003104 return task_step(task, NULL);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003105 default:
3106 assert(res == 1);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003107 result = task_step(task, fut_result);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003108 Py_DECREF(fut_result);
3109 return result;
3110 }
3111 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003112 else {
Serhiy Storchakabca49392017-09-03 08:10:14 +03003113 PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
3114 if (fut_result != NULL) {
3115 Py_DECREF(fut_result);
Yury Selivanov22feeb82018-01-24 11:31:01 -05003116 return task_step(task, NULL);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003117 }
3118 /* exception raised */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003119 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003120
3121 PyErr_Fetch(&et, &ev, &tb);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003122 if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
3123 PyErr_NormalizeException(&et, &ev, &tb);
3124 }
3125
Yury Selivanov22feeb82018-01-24 11:31:01 -05003126 result = task_step(task, ev);
Serhiy Storchakabca49392017-09-03 08:10:14 +03003127
3128 Py_DECREF(et);
3129 Py_XDECREF(tb);
3130 Py_XDECREF(ev);
3131
3132 return result;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003133}
3134
3135
Yury Selivanova70232f2017-12-13 14:49:42 -05003136/*********************** Functions **************************/
3137
3138
3139/*[clinic input]
3140_asyncio._get_running_loop
3141
3142Return the running event loop or None.
3143
3144This is a low-level function intended to be used by event loops.
3145This function is thread-specific.
3146
3147[clinic start generated code]*/
3148
3149static PyObject *
3150_asyncio__get_running_loop_impl(PyObject *module)
3151/*[clinic end generated code: output=b4390af721411a0a input=0a21627e25a4bd43]*/
3152{
3153 PyObject *loop;
3154 if (get_running_loop(&loop)) {
3155 return NULL;
3156 }
3157 if (loop == NULL) {
3158 /* There's no currently running event loop */
3159 Py_RETURN_NONE;
3160 }
3161 return loop;
3162}
3163
3164/*[clinic input]
3165_asyncio._set_running_loop
3166 loop: 'O'
3167 /
3168
3169Set the running event loop.
3170
3171This is a low-level function intended to be used by event loops.
3172This function is thread-specific.
3173[clinic start generated code]*/
3174
3175static PyObject *
3176_asyncio__set_running_loop(PyObject *module, PyObject *loop)
3177/*[clinic end generated code: output=ae56bf7a28ca189a input=4c9720233d606604]*/
3178{
3179 if (set_running_loop(loop)) {
3180 return NULL;
3181 }
3182 Py_RETURN_NONE;
3183}
3184
3185/*[clinic input]
3186_asyncio.get_event_loop
3187
3188Return an asyncio event loop.
3189
3190When called from a coroutine or a callback (e.g. scheduled with
3191call_soon or similar API), this function will always return the
3192running event loop.
3193
3194If there is no running event loop set, the function will return
3195the result of `get_event_loop_policy().get_event_loop()` call.
3196[clinic start generated code]*/
3197
3198static PyObject *
3199_asyncio_get_event_loop_impl(PyObject *module)
3200/*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/
3201{
3202 return get_event_loop();
3203}
3204
3205/*[clinic input]
3206_asyncio.get_running_loop
3207
3208Return the running event loop. Raise a RuntimeError if there is none.
3209
3210This function is thread-specific.
3211[clinic start generated code]*/
3212
3213static PyObject *
3214_asyncio_get_running_loop_impl(PyObject *module)
3215/*[clinic end generated code: output=c247b5f9e529530e input=2a3bf02ba39f173d]*/
3216{
3217 PyObject *loop;
3218 if (get_running_loop(&loop)) {
3219 return NULL;
3220 }
3221 if (loop == NULL) {
3222 /* There's no currently running event loop */
3223 PyErr_SetString(
3224 PyExc_RuntimeError, "no running event loop");
3225 }
3226 return loop;
3227}
3228
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003229/*[clinic input]
3230_asyncio._register_task
3231
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003232 task: object
3233
3234Register a new task in asyncio as executed by loop.
3235
3236Returns None.
3237[clinic start generated code]*/
3238
3239static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003240_asyncio__register_task_impl(PyObject *module, PyObject *task)
3241/*[clinic end generated code: output=8672dadd69a7d4e2 input=21075aaea14dfbad]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003242{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003243 if (register_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003244 return NULL;
3245 }
3246 Py_RETURN_NONE;
3247}
3248
3249
3250/*[clinic input]
3251_asyncio._unregister_task
3252
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003253 task: object
3254
3255Unregister a task.
3256
3257Returns None.
3258[clinic start generated code]*/
3259
3260static PyObject *
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003261_asyncio__unregister_task_impl(PyObject *module, PyObject *task)
3262/*[clinic end generated code: output=6e5585706d568a46 input=28fb98c3975f7bdc]*/
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003263{
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003264 if (unregister_task(task) < 0) {
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003265 return NULL;
3266 }
3267 Py_RETURN_NONE;
3268}
3269
3270
3271/*[clinic input]
3272_asyncio._enter_task
3273
3274 loop: object
3275 task: object
3276
3277Enter into task execution or resume suspended task.
3278
3279Task belongs to loop.
3280
3281Returns None.
3282[clinic start generated code]*/
3283
3284static PyObject *
3285_asyncio__enter_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3286/*[clinic end generated code: output=a22611c858035b73 input=de1b06dca70d8737]*/
3287{
3288 if (enter_task(loop, task) < 0) {
3289 return NULL;
3290 }
3291 Py_RETURN_NONE;
3292}
3293
3294
3295/*[clinic input]
3296_asyncio._leave_task
3297
3298 loop: object
3299 task: object
3300
3301Leave task execution or suspend a task.
3302
3303Task belongs to loop.
3304
3305Returns None.
3306[clinic start generated code]*/
3307
3308static PyObject *
3309_asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
3310/*[clinic end generated code: output=0ebf6db4b858fb41 input=51296a46313d1ad8]*/
3311{
3312 if (leave_task(loop, task) < 0) {
3313 return NULL;
3314 }
3315 Py_RETURN_NONE;
3316}
3317
Yury Selivanova70232f2017-12-13 14:49:42 -05003318
Yury Selivanov9d411c12018-01-23 15:10:03 -05003319/*********************** PyRunningLoopHolder ********************/
3320
3321
3322static PyRunningLoopHolder *
3323new_running_loop_holder(PyObject *loop)
3324{
3325 PyRunningLoopHolder *rl = PyObject_New(
3326 PyRunningLoopHolder, &PyRunningLoopHolder_Type);
3327 if (rl == NULL) {
3328 return NULL;
3329 }
3330
3331#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
3332 rl->rl_pid = getpid();
3333#endif
3334
3335 Py_INCREF(loop);
3336 rl->rl_loop = loop;
3337
3338 return rl;
3339}
3340
3341
3342static void
3343PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
3344{
3345 Py_CLEAR(rl->rl_loop);
3346 PyObject_Free(rl);
3347}
3348
3349
3350static PyTypeObject PyRunningLoopHolder_Type = {
3351 PyVarObject_HEAD_INIT(NULL, 0)
3352 "_RunningLoopHolder",
3353 sizeof(PyRunningLoopHolder),
3354 .tp_getattro = PyObject_GenericGetAttr,
3355 .tp_flags = Py_TPFLAGS_DEFAULT,
3356 .tp_dealloc = (destructor)PyRunningLoopHolder_tp_dealloc,
3357};
3358
3359
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003360/*********************** Module **************************/
3361
3362
3363static void
Zackery Spytze40ad792017-12-19 11:48:13 -07003364module_free_freelists(void)
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003365{
3366 PyObject *next;
3367 PyObject *current;
3368
3369 next = (PyObject*) fi_freelist;
3370 while (next != NULL) {
3371 assert(fi_freelist_len > 0);
3372 fi_freelist_len--;
3373
3374 current = next;
3375 next = (PyObject*) ((futureiterobject*) current)->future;
3376 PyObject_GC_Del(current);
3377 }
3378 assert(fi_freelist_len == 0);
3379 fi_freelist = NULL;
3380}
3381
3382
3383static void
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003384module_free(void *m)
3385{
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003386 Py_CLEAR(asyncio_mod);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003387 Py_CLEAR(traceback_extract_stack);
3388 Py_CLEAR(asyncio_future_repr_info_func);
3389 Py_CLEAR(asyncio_get_event_loop_policy);
3390 Py_CLEAR(asyncio_iscoroutine_func);
3391 Py_CLEAR(asyncio_task_get_stack_func);
3392 Py_CLEAR(asyncio_task_print_stack_func);
3393 Py_CLEAR(asyncio_task_repr_info_func);
3394 Py_CLEAR(asyncio_InvalidStateError);
3395 Py_CLEAR(asyncio_CancelledError);
3396
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003397 Py_CLEAR(all_tasks);
Yury Selivanova9d7e552017-12-19 07:18:45 -05003398 Py_CLEAR(current_tasks);
3399 Py_CLEAR(iscoroutine_typecache);
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003400
Yury Selivanovf23746a2018-01-22 19:11:18 -05003401 Py_CLEAR(context_kwname);
3402
Yury Selivanov1b7c11f2017-12-17 20:19:47 -05003403 module_free_freelists();
Jeffrey Quesnellea75e7302020-04-16 22:09:45 -04003404
3405 module_initialized = 0;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003406}
3407
3408static int
3409module_init(void)
3410{
3411 PyObject *module = NULL;
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003412
3413 asyncio_mod = PyImport_ImportModule("asyncio");
3414 if (asyncio_mod == NULL) {
3415 goto fail;
3416 }
Ben Harper321def82019-10-07 12:19:58 -04003417 if (module_initialized != 0) {
3418 return 0;
Andrew Svetlov969ae7a2019-12-07 13:23:21 +02003419 }
Ben Harper321def82019-10-07 12:19:58 -04003420 else {
3421 module_initialized = 1;
3422 }
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003423
3424 current_tasks = PyDict_New();
3425 if (current_tasks == NULL) {
3426 goto fail;
3427 }
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003428
Yury Selivanova9d7e552017-12-19 07:18:45 -05003429 iscoroutine_typecache = PySet_New(NULL);
3430 if (iscoroutine_typecache == NULL) {
3431 goto fail;
3432 }
3433
Yury Selivanovf23746a2018-01-22 19:11:18 -05003434
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003435 context_kwname = Py_BuildValue("(s)", "context");
Yury Selivanovf23746a2018-01-22 19:11:18 -05003436 if (context_kwname == NULL) {
3437 goto fail;
3438 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05003439
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003440#define WITH_MOD(NAME) \
3441 Py_CLEAR(module); \
3442 module = PyImport_ImportModule(NAME); \
3443 if (module == NULL) { \
Serhiy Storchakabca49392017-09-03 08:10:14 +03003444 goto fail; \
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003445 }
3446
3447#define GET_MOD_ATTR(VAR, NAME) \
3448 VAR = PyObject_GetAttrString(module, NAME); \
3449 if (VAR == NULL) { \
3450 goto fail; \
3451 }
3452
3453 WITH_MOD("asyncio.events")
Yury Selivanova70232f2017-12-13 14:49:42 -05003454 GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003455
3456 WITH_MOD("asyncio.base_futures")
3457 GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
Andrew Svetlov0baa72f2018-09-11 10:13:04 -07003458
3459 WITH_MOD("asyncio.exceptions")
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003460 GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
3461 GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
3462
3463 WITH_MOD("asyncio.base_tasks")
3464 GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
3465 GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
3466 GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
3467
Andrew Svetlovf74ef452017-12-15 07:04:38 +02003468 WITH_MOD("asyncio.coroutines")
3469 GET_MOD_ATTR(asyncio_iscoroutine_func, "iscoroutine")
3470
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003471 WITH_MOD("traceback")
3472 GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
3473
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003474 PyObject *weak_set;
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003475 WITH_MOD("weakref")
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003476 GET_MOD_ATTR(weak_set, "WeakSet");
Victor Stinner2ff58a22019-06-17 14:27:23 +02003477 all_tasks = PyObject_CallNoArgs(weak_set);
Yury Selivanovca9b36c2017-12-23 15:04:15 -05003478 Py_CLEAR(weak_set);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003479 if (all_tasks == NULL) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003480 goto fail;
3481 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003482
Serhiy Storchakabca49392017-09-03 08:10:14 +03003483 Py_DECREF(module);
INADA Naokic411a7d2016-10-18 11:48:14 +09003484 return 0;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003485
INADA Naokic411a7d2016-10-18 11:48:14 +09003486fail:
INADA Naokic411a7d2016-10-18 11:48:14 +09003487 Py_CLEAR(module);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003488 module_free(NULL);
INADA Naokic411a7d2016-10-18 11:48:14 +09003489 return -1;
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003490
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003491#undef WITH_MOD
3492#undef GET_MOD_ATTR
3493}
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003494
INADA Naokic411a7d2016-10-18 11:48:14 +09003495PyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003496
Yury Selivanova70232f2017-12-13 14:49:42 -05003497static PyMethodDef asyncio_methods[] = {
3498 _ASYNCIO_GET_EVENT_LOOP_METHODDEF
3499 _ASYNCIO_GET_RUNNING_LOOP_METHODDEF
3500 _ASYNCIO__GET_RUNNING_LOOP_METHODDEF
3501 _ASYNCIO__SET_RUNNING_LOOP_METHODDEF
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003502 _ASYNCIO__REGISTER_TASK_METHODDEF
3503 _ASYNCIO__UNREGISTER_TASK_METHODDEF
3504 _ASYNCIO__ENTER_TASK_METHODDEF
3505 _ASYNCIO__LEAVE_TASK_METHODDEF
Yury Selivanova70232f2017-12-13 14:49:42 -05003506 {NULL, NULL}
3507};
3508
INADA Naoki9f2ce252016-10-15 15:39:19 +09003509static struct PyModuleDef _asynciomodule = {
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003510 PyModuleDef_HEAD_INIT, /* m_base */
INADA Naoki9f2ce252016-10-15 15:39:19 +09003511 "_asyncio", /* m_name */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003512 module_doc, /* m_doc */
3513 -1, /* m_size */
Yury Selivanova70232f2017-12-13 14:49:42 -05003514 asyncio_methods, /* m_methods */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003515 NULL, /* m_slots */
3516 NULL, /* m_traverse */
3517 NULL, /* m_clear */
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003518 (freefunc)module_free /* m_free */
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003519};
3520
3521
3522PyMODINIT_FUNC
INADA Naoki9f2ce252016-10-15 15:39:19 +09003523PyInit__asyncio(void)
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003524{
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003525 if (module_init() < 0) {
INADA Naokic411a7d2016-10-18 11:48:14 +09003526 return NULL;
3527 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003528 if (PyType_Ready(&FutureIterType) < 0) {
3529 return NULL;
3530 }
Serhiy Storchakabca49392017-09-03 08:10:14 +03003531 if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003532 return NULL;
3533 }
Serhiy Storchakafb3e9c02018-09-21 09:11:32 +03003534 if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003535 return NULL;
3536 }
Yury Selivanov9d411c12018-01-23 15:10:03 -05003537 if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) {
3538 return NULL;
3539 }
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003540
INADA Naoki9f2ce252016-10-15 15:39:19 +09003541 PyObject *m = PyModule_Create(&_asynciomodule);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003542 if (m == NULL) {
3543 return NULL;
3544 }
3545
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003546 /* FutureType and TaskType are made ready by PyModule_AddType() calls below. */
3547 if (PyModule_AddType(m, &FutureType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003548 Py_DECREF(m);
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003549 return NULL;
3550 }
3551
Dong-hee Na37fcbb62020-03-25 07:08:51 +09003552 if (PyModule_AddType(m, &TaskType) < 0) {
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003553 Py_DECREF(m);
Yury Selivanova0c1ba62016-10-28 12:52:37 -04003554 return NULL;
3555 }
3556
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003557 Py_INCREF(all_tasks);
3558 if (PyModule_AddObject(m, "_all_tasks", all_tasks) < 0) {
3559 Py_DECREF(all_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003560 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003561 return NULL;
3562 }
3563
3564 Py_INCREF(current_tasks);
3565 if (PyModule_AddObject(m, "_current_tasks", current_tasks) < 0) {
3566 Py_DECREF(current_tasks);
Brandt Bucherc3f6bdc2019-11-16 14:26:54 -08003567 Py_DECREF(m);
Andrew Svetlov44d1a592017-12-16 21:58:38 +02003568 return NULL;
3569 }
3570
INADA Naoki9e4e38e2016-10-09 14:44:47 +09003571 return m;
3572}