diff options
| author | Negulici-R. Barnabas <109497789+negulici-r-barnabas@users.noreply.github.com> | 2022-07-25 07:16:04 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-25 07:16:04 +0300 |
| commit | a1f1fd9a5ca193f60ab1833b3f0c91ca68f38bed (patch) | |
| tree | 419f2a8a95f377eca49966fc1f746287a303b709 | |
| parent | 4fac67c097ac0328fcc5deb1b6264ea3cec4ce5b (diff) | |
| parent | bffda19bbc9d8fe95c864d7315a0c6f6a05d9d7d (diff) | |
Merge branch 'jellyfin:master' into master
8 files changed, 120 insertions, 13 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 32289625f..bc55dc6b4 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -111,7 +111,7 @@ namespace Emby.Server.Implementations /// <summary> /// Class CompositionRoot. /// </summary> - public abstract class ApplicationHost : IServerApplicationHost, IDisposable + public abstract class ApplicationHost : IServerApplicationHost, IAsyncDisposable, IDisposable { /// <summary> /// The environment variable prefixes to log at server startup. @@ -1232,5 +1232,49 @@ namespace Emby.Server.Implementations _disposed = true; } + + public async ValueTask DisposeAsync() + { + await DisposeAsyncCore().ConfigureAwait(false); + Dispose(false); + GC.SuppressFinalize(this); + } + + /// <summary> + /// Used to perform asynchronous cleanup of managed resources or for cascading calls to <see cref="DisposeAsync"/>. + /// </summary> + /// <returns>A ValueTask.</returns> + protected virtual async ValueTask DisposeAsyncCore() + { + var type = GetType(); + + Logger.LogInformation("Disposing {Type}", type.Name); + + foreach (var (part, _) in _disposableParts) + { + var partType = part.GetType(); + if (partType == type) + { + continue; + } + + Logger.LogInformation("Disposing {Type}", partType.Name); + + try + { + part.Dispose(); + } + catch (Exception ex) + { + Logger.LogError(ex, "Error disposing {Type}", partType.Name); + } + } + + // used for closing websockets + foreach (var session in _sessionManager.Sessions) + { + await session.DisposeAsync().ConfigureAwait(false); + } + } } } diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 4361440d7..1b176e60d 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -4934,6 +4934,7 @@ SELECT key FROM UserDatas WHERE isFavorite=@IsFavorite AND userId=@UserId) AND Type = @InternalPersonType)"); statement?.TryBind("@IsFavorite", query.IsFavorite.Value); statement?.TryBind("@InternalPersonType", typeof(Person).FullName); + statement?.TryBind("@UserId", query.User.InternalId); } if (!query.ItemId.Equals(default)) @@ -4988,11 +4989,6 @@ AND Type = @InternalPersonType)"); statement?.TryBind("@NameContains", "%" + query.NameContains + "%"); } - if (query.User != null) - { - statement?.TryBind("@UserId", query.User.InternalId); - } - return whereClauses; } diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index b87f1bc22..818ccbb1b 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.HttpServer /// <summary> /// Class WebSocketConnection. /// </summary> - public class WebSocketConnection : IWebSocketConnection, IDisposable + public class WebSocketConnection : IWebSocketConnection { /// <summary> /// The logger. @@ -36,6 +36,8 @@ namespace Emby.Server.Implementations.HttpServer /// </summary> private readonly WebSocket _socket; + private bool _disposed = false; + /// <summary> /// Initializes a new instance of the <see cref="WebSocketConnection" /> class. /// </summary> @@ -244,10 +246,39 @@ namespace Emby.Server.Implementations.HttpServer /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected virtual void Dispose(bool dispose) { + if (_disposed) + { + return; + } + if (dispose) { _socket.Dispose(); } + + _disposed = true; + } + + /// <inheritdoc /> + public async ValueTask DisposeAsync() + { + await DisposeAsyncCore().ConfigureAwait(false); + Dispose(false); + GC.SuppressFinalize(this); + } + + /// <summary> + /// Used to perform asynchronous cleanup of managed resources or for cascading calls to <see cref="DisposeAsync"/>. + /// </summary> + /// <returns>A ValueTask.</returns> + protected virtual async ValueTask DisposeAsyncCore() + { + if (_socket.State == WebSocketState.Open) + { + await _socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "System Shutdown", CancellationToken.None).ConfigureAwait(false); + } + + _socket.Dispose(); } } } diff --git a/Emby.Server.Implementations/Session/WebSocketController.cs b/Emby.Server.Implementations/Session/WebSocketController.cs index d21b6a929..1f3248f07 100644 --- a/Emby.Server.Implementations/Session/WebSocketController.cs +++ b/Emby.Server.Implementations/Session/WebSocketController.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Session { - public sealed class WebSocketController : ISessionController, IDisposable + public sealed class WebSocketController : ISessionController, IAsyncDisposable, IDisposable { private readonly ILogger<WebSocketController> _logger; private readonly ISessionManager _sessionManager; @@ -99,6 +99,23 @@ namespace Emby.Server.Implementations.Session foreach (var socket in _sockets) { socket.Closed -= OnConnectionClosed; + socket.Dispose(); + } + + _disposed = true; + } + + public async ValueTask DisposeAsync() + { + if (_disposed) + { + return; + } + + foreach (var socket in _sockets) + { + socket.Closed -= OnConnectionClosed; + await socket.DisposeAsync().ConfigureAwait(false); } _disposed = true; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 2bda8d290..a6f0b705d 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -243,7 +243,7 @@ namespace Jellyfin.Server } } - appHost.Dispose(); + await appHost.DisposeAsync().ConfigureAwait(false); } if (_restartOnShutdown) diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 91acca0a7..15afde601 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -4970,7 +4970,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.InputProtocol == MediaProtocol.Rtsp) { - inputModifier += " -rtsp_transport tcp -rtsp_transport udp -rtsp_flags prefer_tcp"; + inputModifier += " -rtsp_transport tcp+udp -rtsp_flags prefer_tcp"; } if (!string.IsNullOrEmpty(state.InputAudioSync)) diff --git a/MediaBrowser.Controller/Net/IWebSocketConnection.cs b/MediaBrowser.Controller/Net/IWebSocketConnection.cs index 2c6483ae2..43c7ce370 100644 --- a/MediaBrowser.Controller/Net/IWebSocketConnection.cs +++ b/MediaBrowser.Controller/Net/IWebSocketConnection.cs @@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Http; namespace MediaBrowser.Controller.Net { - public interface IWebSocketConnection + public interface IWebSocketConnection : IAsyncDisposable, IDisposable { /// <summary> /// Occurs when [closed]. diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index c2ca23386..b4520ae48 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; using System.Threading; +using System.Threading.Tasks; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Session; @@ -17,7 +18,7 @@ namespace MediaBrowser.Controller.Session /// <summary> /// Class SessionInfo. /// </summary> - public sealed class SessionInfo : IDisposable + public sealed class SessionInfo : IAsyncDisposable, IDisposable { // 1 second private const long ProgressIncrement = 10000000; @@ -380,10 +381,28 @@ namespace MediaBrowser.Controller.Session { if (controller is IDisposable disposable) { - _logger.LogDebug("Disposing session controller {0}", disposable.GetType().Name); + _logger.LogDebug("Disposing session controller synchronously {TypeName}", disposable.GetType().Name); disposable.Dispose(); } } } + + public async ValueTask DisposeAsync() + { + _disposed = true; + + StopAutomaticProgress(); + + var controllers = SessionControllers.ToList(); + + foreach (var controller in controllers) + { + if (controller is IAsyncDisposable disposableAsync) + { + _logger.LogDebug("Disposing session controller asynchronously {TypeName}", disposableAsync.GetType().Name); + await disposableAsync.DisposeAsync().ConfigureAwait(false); + } + } + } } } |
