Skip to content

Commit 7b815c8

Browse files
committed
Address code quality review comments
- Guard SocketPairAsyncioConnection definition with ASYNCIO_AVAILABLE check to avoid subclassing NoneType when asyncio is unavailable - Add debug logging in close() except block instead of bare pass - Add inline comments to except blocks in _close() for remove_reader/remove_writer
1 parent e86d53b commit 7b815c8

2 files changed

Lines changed: 20 additions & 23 deletions

File tree

cassandra/io/asyncioreactor.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,9 @@ def close(self):
155155
try:
156156
future.result(timeout=5)
157157
except Exception:
158-
pass
158+
# Best-effort close: suppress errors during shutdown
159+
log.debug("Error waiting for async close of %s",
160+
self.endpoint, exc_info=True)
159161

160162
async def _close(self):
161163
log.debug("Closing connection (%s) to %s" % (id(self), self.endpoint))
@@ -171,11 +173,11 @@ async def _close(self):
171173
try:
172174
self._loop.remove_writer(self._socket.fileno())
173175
except (NotImplementedError, OSError):
174-
pass
176+
pass # not supported on Windows ProactorEventLoop
175177
try:
176178
self._loop.remove_reader(self._socket.fileno())
177179
except (NotImplementedError, OSError):
178-
pass
180+
pass # not supported on Windows ProactorEventLoop
179181
self._socket.close()
180182

181183
log.debug("Closed socket to %s" % (self.endpoint,))
@@ -246,9 +248,6 @@ async def handle_write(self):
246248
self, err)
247249
self.close()
248250
return
249-
# Connection is already shutting down, just exit
250-
if self.is_closed or self.is_defunct:
251-
return
252251
log.debug("Exception in send for %s: %s", self, err)
253252
self.defunct(err)
254253
return
@@ -270,9 +269,6 @@ async def handle_read(self):
270269
await asyncio.sleep(0)
271270
continue
272271
except socket.error as err:
273-
# Connection is already shutting down, just exit
274-
if self.is_closed or self.is_defunct:
275-
return
276272
log.debug("Exception during socket recv for %s: %s",
277273
self, err)
278274
self.defunct(err)

tests/unit/io/test_asyncio_race_614.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,24 +49,25 @@
4949
skip_me = is_monkey_patched() or not ASYNCIO_AVAILABLE
5050

5151

52-
class SocketPairAsyncioConnection(AsyncioConnection):
53-
"""
54-
A subclass of AsyncioConnection that uses a pre-provided socket from
55-
a socketpair instead of connecting to a real CQL server.
52+
if ASYNCIO_AVAILABLE and AsyncioConnection is not None:
53+
class SocketPairAsyncioConnection(AsyncioConnection):
54+
"""
55+
A subclass of AsyncioConnection that uses a pre-provided socket from
56+
a socketpair instead of connecting to a real CQL server.
5657
57-
This bypasses _connect_socket() and _send_options_message() so we can
58-
test I/O race conditions with a real fd registered on the event loop.
59-
"""
58+
This bypasses _connect_socket() and _send_options_message() so we can
59+
test I/O race conditions with a real fd registered on the event loop.
60+
"""
6061

61-
_test_socket = None # Set before __init__
62+
_test_socket = None # Set before __init__
6263

63-
def _connect_socket(self):
64-
"""Use the pre-provided test socket instead of connecting."""
65-
self._socket = self._test_socket
64+
def _connect_socket(self):
65+
"""Use the pre-provided test socket instead of connecting."""
66+
self._socket = self._test_socket
6667

67-
def _send_options_message(self):
68-
"""Skip the CQL handshake -- we don't have a real server."""
69-
pass
68+
def _send_options_message(self):
69+
"""Skip the CQL handshake -- we don't have a real server."""
70+
pass
7071

7172

7273
def _make_connection_with_socketpair():

0 commit comments

Comments
 (0)