Skip to content

Commit 4a08100

Browse files
sebrclaude
andauthored
Fix websocket "Cannot write to closing transport" error (#373)
Fixes #156 Prevent race condition where heartbeat ping attempts to send data on a closing websocket connection: - Add closed state check in _ping() before sending - Wrap ping send in try/except to handle connection errors gracefully - Cancel heartbeat callback when websocket closes or stops 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent e3edc08 commit 4a08100

1 file changed

Lines changed: 10 additions & 3 deletions

File tree

custom_components/bhyve/pybhyve/websocket.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,14 @@ def _send_heartbeat(self) -> None:
6767
self._loop.create_task(self._ping())
6868

6969
async def _ping(self) -> None:
70-
if self._ws is not None:
71-
await self._ws.send_str(json.dumps({"event": "ping"}))
72-
self._reset_heartbeat()
70+
if self._ws is not None and not self._ws.closed:
71+
try:
72+
await self._ws.send_str(json.dumps({"event": "ping"}))
73+
self._reset_heartbeat()
74+
except ConnectionResetError:
75+
_LOGGER.debug("Connection reset while sending ping")
76+
except Exception as err: # noqa: BLE001
77+
_LOGGER.debug("Error sending ping: %s", err)
7378

7479
@property
7580
def state(self) -> str:
@@ -146,6 +151,7 @@ async def running(self) -> None: # noqa: PLR0912, PLR0915
146151

147152
if self._ws.closed:
148153
_LOGGER.info("Websocket closed? %s", self._ws.closed)
154+
self._cancel_heartbeat()
149155
self.state = STATE_STOPPED
150156

151157
if self._ws.exception():
@@ -173,6 +179,7 @@ async def stop(self) -> None:
173179
"""Close websocket connection."""
174180
_LOGGER.info("Closing websocket connection; state: %s --> STOPPED", self.state)
175181
self.state = STATE_STOPPED
182+
self._cancel_heartbeat()
176183
if self._ws is not None:
177184
await self._ws.close()
178185

0 commit comments

Comments
 (0)