--- /dev/null
+.. change::
+ :tags: bug, asyncio, postgresql
+ :tickets: 6652
+
+ Fixed bug in asyncio implementation where the greenlet adaptation system
+ failed to propagate ``BaseException`` subclasses, most notably including
+ ``asyncio.CancelledError``, to the exception handling logic used by the
+ engine to invalidate and clean up the connection, thus preventing
+ connections from being correctly disposed when a task was cancelled.
+
+
def is_exit_exception(e):
+ # note asyncio.CancelledError is already BaseException
+ # so was an exit exception in any case
return not isinstance(e, Exception) or isinstance(
e, (asyncio.TimeoutError, asyncio.CancelledError)
)
# wait for a coroutine from await_ and then return its
# result back to it.
value = await result
- except Exception:
+ except BaseException:
# this allows an exception to be raised within
# the moderated greenlet so that it can continue
# its expected flow.
with expect_raises_message(ValueError, "an error"):
await greenlet_spawn(go, run1, err)
+ @async_test
+ async def test_propagate_cancelled(self):
+ """test #6652"""
+ cleanup = []
+
+ async def async_meth_raise():
+ raise asyncio.CancelledError()
+
+ def sync_meth():
+ try:
+ await_only(async_meth_raise())
+ except:
+ cleanup.append(True)
+ raise
+
+ async def run_w_cancel():
+ await greenlet_spawn(sync_meth)
+
+ with expect_raises(asyncio.CancelledError, check_context=False):
+ await run_w_cancel()
+
+ assert cleanup
+
@async_test
async def test_sync_error(self):
def go():