Skip to content

Conversation

Josef-MrBeam
Copy link

If your client device loose the network connection to the device running the websocket server this will not be detected by the socket client.
This watchdog will be reseted by the heartbeat message (appears every 25 seconds) if the watchdog will not be resetted in a 30 second window the connection can be marked as lost => 1006

Found with OctoPrint, if you connect to the OctoPrint instance with a laptop and this goes to sleep mode for some time (network will be disabled)
After you wake the device again you still see the UI but the websocket connection is not connected anymore.

You can reproduce this by disabling your network on the laptop, wait some time and connect again.

Copy link
Member

@auvipy auvipy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the patch, can you please add some tests for the change?

@auvipy auvipy requested a review from Copilot August 7, 2025 06:30
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a watchdog timer mechanism to detect lost WebSocket connections that aren't properly detected by the socket client. The watchdog is reset by heartbeat messages (which occur every 25 seconds) and triggers a connection close if no heartbeat is received within 30 seconds.

  • Adds a 30-second timeout constant for the watchdog mechanism
  • Implements a watchdog callback function that closes the connection with code 1006
  • Sets up and resets the watchdog timer on heartbeat messages and connection open

Comment on lines +245 to +247
SockJS.prototype._websocketWatchdogCb = function(websocket) {
debug("watchdog websocket timeout");
websocket._close(1006, 'Server lost session');
Copy link
Preview

Copilot AI Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name 'websocket' is misleading as it refers to the SockJS instance, not a WebSocket. This should be 'sockjs' or 'self' to accurately reflect what it represents.

Suggested change
SockJS.prototype._websocketWatchdogCb = function(websocket) {
debug("watchdog websocket timeout");
websocket._close(1006, 'Server lost session');
SockJS.prototype._websocketWatchdogCb = function(sockjs) {
debug("watchdog websocket timeout");
sockjs._close(1006, 'Server lost session');

Copilot uses AI. Check for mistakes.

@@ -257,6 +263,8 @@ SockJS.prototype._transportMessage = function(msg) {
case 'h':
this.dispatchEvent(new Event('heartbeat'));
debug('heartbeat', this.transport);
clearTimeout(this.heartbeatWatchdog);
this.heartbeatWatchdog = setTimeout(this._websocketWatchdogCb, SockJS.WATCHDOG_WEBSOCKET_TIMEOUT, this);
Copy link
Preview

Copilot AI Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The watchdog timer should be cleared when the connection is closed to prevent potential memory leaks and unexpected behavior. Consider adding clearTimeout(this.heartbeatWatchdog) in the _close method.

Copilot uses AI. Check for mistakes.

Co-authored-by: Copilot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants