fix: use a reentrant lock when accessing active connections (#11256)

pull/11260/head
Claus Vium 2 months ago committed by GitHub
parent fe88a484d1
commit 4201079b34
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -48,7 +48,7 @@ namespace Emby.Server.Implementations.HttpServer
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false); WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false);
using var connection = new WebSocketConnection( var connection = new WebSocketConnection(
_loggerFactory.CreateLogger<WebSocketConnection>(), _loggerFactory.CreateLogger<WebSocketConnection>(),
webSocket, webSocket,
authorizationInfo, authorizationInfo,
@ -56,17 +56,19 @@ namespace Emby.Server.Implementations.HttpServer
{ {
OnReceive = ProcessWebSocketMessageReceived OnReceive = ProcessWebSocketMessageReceived
}; };
await using (connection.ConfigureAwait(false))
var tasks = new Task[_webSocketListeners.Length];
for (var i = 0; i < _webSocketListeners.Length; ++i)
{ {
tasks[i] = _webSocketListeners[i].ProcessWebSocketConnectedAsync(connection, context); var tasks = new Task[_webSocketListeners.Length];
} for (var i = 0; i < _webSocketListeners.Length; ++i)
{
tasks[i] = _webSocketListeners[i].ProcessWebSocketConnectedAsync(connection, context);
}
await Task.WhenAll(tasks).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false);
await connection.ReceiveAsync().ConfigureAwait(false); await connection.ReceiveAsync().ConfigureAwait(false);
_logger.LogInformation("WS {IP} closed", context.Connection.RemoteIpAddress); _logger.LogInformation("WS {IP} closed", context.Connection.RemoteIpAddress);
}
} }
catch (Exception ex) // Otherwise ASP.Net will ignore the exception catch (Exception ex) // Otherwise ASP.Net will ignore the exception
{ {

@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Net
SingleWriter = false SingleWriter = false
}); });
private readonly SemaphoreSlim _lock = new(1, 1); private readonly object _activeConnectionsLock = new();
/// <summary> /// <summary>
/// The _active connections. /// The _active connections.
@ -126,15 +126,10 @@ namespace MediaBrowser.Controller.Net
InitialDelayMs = dueTimeMs InitialDelayMs = dueTimeMs
}; };
_lock.Wait(); lock (_activeConnectionsLock)
try
{ {
_activeConnections.Add((message.Connection, cancellationTokenSource, state)); _activeConnections.Add((message.Connection, cancellationTokenSource, state));
} }
finally
{
_lock.Release();
}
} }
protected void SendData(bool force) protected void SendData(bool force)
@ -153,8 +148,7 @@ namespace MediaBrowser.Controller.Net
(IWebSocketConnection Connection, CancellationTokenSource CancellationTokenSource, TStateType State)[] tuples; (IWebSocketConnection Connection, CancellationTokenSource CancellationTokenSource, TStateType State)[] tuples;
var now = DateTime.UtcNow; var now = DateTime.UtcNow;
await _lock.WaitAsync().ConfigureAwait(false); lock (_activeConnectionsLock)
try
{ {
if (_activeConnections.Count == 0) if (_activeConnections.Count == 0)
{ {
@ -174,10 +168,6 @@ namespace MediaBrowser.Controller.Net
}) })
.ToArray(); .ToArray();
} }
finally
{
_lock.Release();
}
if (tuples.Length == 0) if (tuples.Length == 0)
{ {
@ -240,8 +230,7 @@ namespace MediaBrowser.Controller.Net
/// <param name="message">The message.</param> /// <param name="message">The message.</param>
private void Stop(WebSocketMessageInfo message) private void Stop(WebSocketMessageInfo message)
{ {
_lock.Wait(); lock (_activeConnectionsLock)
try
{ {
var connection = _activeConnections.FirstOrDefault(c => c.Connection == message.Connection); var connection = _activeConnections.FirstOrDefault(c => c.Connection == message.Connection);
@ -250,10 +239,6 @@ namespace MediaBrowser.Controller.Net
DisposeConnection(connection); DisposeConnection(connection);
} }
} }
finally
{
_lock.Release();
}
} }
/// <summary> /// <summary>
@ -283,15 +268,10 @@ namespace MediaBrowser.Controller.Net
Logger.LogError(ex, "Error disposing websocket"); Logger.LogError(ex, "Error disposing websocket");
} }
_lock.Wait(); lock (_activeConnectionsLock)
try
{ {
_activeConnections.Remove(connection); _activeConnections.Remove(connection);
} }
finally
{
_lock.Release();
}
} }
protected virtual async ValueTask DisposeAsyncCore() protected virtual async ValueTask DisposeAsyncCore()
@ -306,18 +286,13 @@ namespace MediaBrowser.Controller.Net
Logger.LogError(ex, "Disposing the message consumer failed"); Logger.LogError(ex, "Disposing the message consumer failed");
} }
await _lock.WaitAsync().ConfigureAwait(false); lock (_activeConnectionsLock)
try
{ {
foreach (var connection in _activeConnections.ToArray()) foreach (var connection in _activeConnections.ToArray())
{ {
DisposeConnection(connection); DisposeConnection(connection);
} }
} }
finally
{
_lock.Release();
}
} }
/// <inheritdoc /> /// <inheritdoc />

Loading…
Cancel
Save