diff --git a/asyncpg/protocol/protocol.pxd b/asyncpg/protocol/protocol.pxd index 5f144e55..a9ac8d5f 100644 --- a/asyncpg/protocol/protocol.pxd +++ b/asyncpg/protocol/protocol.pxd @@ -39,8 +39,6 @@ cdef class BaseProtocol(CoreProtocol): bint return_extra object create_future object timeout_handle - object timeout_callback - object completed_callback object conref type record_class bint is_reading diff --git a/asyncpg/protocol/protocol.pyx b/asyncpg/protocol/protocol.pyx index 1f739cc2..487259eb 100644 --- a/asyncpg/protocol/protocol.pyx +++ b/asyncpg/protocol/protocol.pyx @@ -98,8 +98,6 @@ cdef class BaseProtocol(CoreProtocol): self.writing_allowed.set() self.timeout_handle = None - self.timeout_callback = self._on_timeout - self.completed_callback = self._on_waiter_completed self.queries_count = 0 @@ -584,6 +582,7 @@ cdef class BaseProtocol(CoreProtocol): self._handle_waiter_on_connection_lost(None) self._terminate() self.transport.abort() + self.transport = None @cython.iterable_coroutine async def close(self, timeout): @@ -754,8 +753,8 @@ cdef class BaseProtocol(CoreProtocol): self.waiter = self.create_future() if timeout is not None: self.timeout_handle = self.loop.call_later( - timeout, self.timeout_callback, self.waiter) - self.waiter.add_done_callback(self.completed_callback) + timeout, self._on_timeout, self.waiter) + self.waiter.add_done_callback(self._on_waiter_completed) return self.waiter cdef _on_result__connect(self, object waiter): diff --git a/tests/test_connect.py b/tests/test_connect.py index f61db61a..1af074f1 100644 --- a/tests/test_connect.py +++ b/tests/test_connect.py @@ -7,6 +7,7 @@ import asyncio import contextlib +import gc import ipaddress import os import pathlib @@ -1846,14 +1847,27 @@ async def worker(): class TestConnectionGC(tb.ClusterTestCase): async def _run_no_explicit_close_test(self): - con = await self.connect() - await con.fetchval("select 123") - proto = con._protocol - conref = weakref.ref(con) - del con - - self.assertIsNone(conref()) - self.assertTrue(proto.is_closed()) + gc_was_enabled = gc.isenabled() + gc.disable() + try: + con = await self.connect() + await con.fetchval("select 123") + proto = con._protocol + conref = weakref.ref(con) + del con + + self.assertIsNone(conref()) + self.assertTrue(proto.is_closed()) + + # tick event loop; asyncio.selector_events._SelectorSocketTransport + # needs a chance to close itself and remove its reference to proto + await asyncio.sleep(0) + protoref = weakref.ref(proto) + del proto + self.assertIsNone(protoref()) + finally: + if gc_was_enabled: + gc.enable() async def test_no_explicit_close_no_debug(self): olddebug = self.loop.get_debug()