The running loop holder cache variable was always set to NULL when
calling set_running_loop.
Now set_running_loop saves the newly created running loop holder in the
cache variable for faster access in get_running_loop.
This fixes a possible memory leak in the C implementation of
asyncio.Task.
(cherry picked from commit d2c349b190)
Co-authored-by: Chris Jerdonek <chris.jerdonek@gmail.com>
if parent `__init__` is not called from a constructor of object derived from `asyncio.Future`
https://bugs.python.org/issue38785
(cherry picked from commit dad6be5ffe)
Co-authored-by: Andrew Svetlov <andrew.svetlov@gmail.com>
* bpo-38321: Fix _asynciomodule.c compiler warning (GH-16493)
bpo-38248, bpo-38321: Fix warning:
modules\_asynciomodule.c(2667):
warning C4102: 'set_exception': unreferenced label
The related goto has been removed by
commit edad4d89e3.
(cherry picked from commit efe74b6369)
* bpo-38321: Fix PyCStructUnionType_update_stgdict() warning (GH-16492)
bpo-22273, bpo-38321: Fix following warning:
modules\_ctypes\stgdict.c(704):
warning C4244: 'initializing': conversion from 'Py_ssize_t' to 'int', possible loss of data
(cherry picked from commit c9a413ede4)
It is now allowed to add new fields at the end of the PyTypeObject struct without having to allocate a dedicated compatibility flag in tp_flags.
This will reduce the risk of running out of bits in the 32-bit tp_flags value.
This will address the common mistake many asyncio users make:
an "except Exception" clause breaking Tasks cancellation.
In addition to this change, we stop inheriting asyncio.TimeoutError
and asyncio.InvalidStateError from their concurrent.futures.*
counterparts. There's no point for these exceptions to share the
inheritance chain.
In 3.9 we'll focus on implementing supervisors and cancel scopes,
which should allow better handling of all exceptions, including
SystemExit and KeyboardInterrupt
The C implementation of asyncio.Task currently fails to perform the
cancellation cleanup correctly in the following scenario.
async def task1():
async def task2():
await task3 # task3 is never cancelled
asyncio.current_task().cancel()
await asyncio.create_task(task2())
The actuall error is a hardcoded call to `future_cancel()` instead of
calling the `cancel()` method of a future-like object.
Thanks to Vladimir Matveev for noticing the code discrepancy and to
Yury Selivanov for coming up with a pathological scenario.
Fix the following bugs in the C implementation:
* get_future_loop() silenced all exceptions raised when look up the get_loop
attribute, not just an AttributeError.
* enter_task() silenced all exceptions raised when look up the current task,
not just a KeyError.
* repr() was called for a borrowed link in enter_task() and task_step_impl().
* str() was used instead of repr() in formatting one error message (in
Python implementation too).
* There where few reference leaks in error cases.
Specifically, it's not possible to subclass Task/Future classes
and override the following methods:
* Future._schedule_callbacks
* Task._step
* Task._wakeup
asyncio.get_event_loop(), and, subsequently asyncio._get_running_loop()
are one of the most frequently executed functions in asyncio. They also
can't be sped up by third-party event loops like uvloop.
When implemented in C they become 4x faster.
when there are no more `await` or `yield (from)` before return in coroutine,
cancel was ignored.
example:
async def coro():
asyncio.Task.current_task().cancel()
return 42
...
res = await coro() # should raise CancelledError