aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
authorEnea D'Angiò <enea.dangio162006@gmail.com>2026-07-02 19:36:48 +0200
committerGitHub <noreply@github.com>2026-07-02 19:36:48 +0200
commit8f3eb3205d61d71638a1c695372cef273e76d2b3 (patch)
tree5014a6a53ab3dced9e4dfd54ed0c1c8f346aae35 /Emby.Server.Implementations
parent379c58a48d8c3a111ae2f08a3392a1286648046b (diff)
Close sessions for lost WebSockets to prevent zombie SyncPlay groups (#17079)
Close sessions for lost WebSockets to prevent zombie SyncPlay groups
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/HttpServer/WebSocketConnection.cs6
-rw-r--r--Emby.Server.Implementations/Session/SessionWebSocketListener.cs15
2 files changed, 19 insertions, 2 deletions
diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
index e9bf3b93a7..dc7f972c13 100644
--- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
+++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
@@ -127,8 +127,12 @@ namespace Emby.Server.Implementations.HttpServer
{
receiveResult = await _socket.ReceiveAsync(memory, cancellationToken).ConfigureAwait(false);
}
- catch (WebSocketException ex)
+ catch (Exception ex) when (ex is WebSocketException or ObjectDisposedException or OperationCanceledException)
{
+ // ObjectDisposedException/OperationCanceledException: the socket was torn
+ // down underneath us (e.g. by the keep-alive watchdog after the connection
+ // was declared lost). Fall through so Closed is still raised and the
+ // session can release this connection.
_logger.LogWarning("WS {IP} error receiving data: {Message}", RemoteEndPoint, ex.Message);
break;
}
diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs
index 6a26e92e14..2582ed9df0 100644
--- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs
+++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs
@@ -246,8 +246,21 @@ namespace Emby.Server.Implementations.Session
_logger.LogInformation("Lost {0} WebSockets.", lost.Count);
foreach (var webSocket in lost)
{
- // TODO: handle session relative to the lost webSocket
RemoveWebSocket(webSocket);
+
+ // The connection stopped answering keep-alives, so a close frame will
+ // never arrive and the pending receive loop would hang forever, keeping
+ // the session (and e.g. its SyncPlay group membership) alive. Disposing
+ // the connection aborts the receive loop, which raises Closed and lets
+ // the session end normally.
+ try
+ {
+ webSocket.Dispose();
+ }
+ catch (Exception exception)
+ {
+ _logger.LogWarning(exception, "Error disposing lost WebSocket from {RemoteEndPoint}.", webSocket.RemoteEndPoint);
+ }
}
}
}