diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 5dc778fdce..7079ca7f5c 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -6,7 +6,7 @@ using System.Net; using System.Net.Security; using System.Reflection; using System.Runtime.InteropServices; -using System.Runtime.Loader; +using System.Threading; using System.Threading.Tasks; using Emby.Drawing; using Emby.Drawing.Skia; @@ -30,12 +30,12 @@ namespace Jellyfin.Server { public static class Program { - private static readonly TaskCompletionSource ApplicationTaskCompletionSource = new TaskCompletionSource(); - private static ILoggerFactory _loggerFactory; + private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource(); + private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory(); private static ILogger _logger; private static bool _restartOnShutdown; - public static async Task Main(string[] args) + public static async Task Main(string[] args) { StartupOptions options = new StartupOptions(args); Version version = Assembly.GetEntryAssembly().GetName().Version; @@ -43,22 +43,33 @@ namespace Jellyfin.Server if (options.ContainsOption("-v") || options.ContainsOption("--version")) { Console.WriteLine(version.ToString()); - return 0; } ServerApplicationPaths appPaths = createApplicationPaths(options); // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath); await createLogger(appPaths); - _loggerFactory = new SerilogLoggerFactory(); _logger = _loggerFactory.CreateLogger("Main"); AppDomain.CurrentDomain.UnhandledException += (sender, e) => _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception"); + // Intercept Ctrl+C and Ctrl+Break + Console.CancelKeyPress += (sender, e) => + { + e.Cancel = true; + _logger.LogInformation("Ctrl+C, shutting down"); + Environment.ExitCode = 2; + Shutdown(); + }; + // Register a SIGTERM handler AppDomain.CurrentDomain.ProcessExit += (sender, e) => { + if (_tokenSource.IsCancellationRequested) + { + return; // Already shutting down + } _logger.LogInformation("Received a SIGTERM signal, shutting down"); Shutdown(); }; @@ -95,7 +106,8 @@ namespace Jellyfin.Server // TODO: read input for a stop command // Block main thread until shutdown - await ApplicationTaskCompletionSource.Task; + await Task.Delay(-1, _tokenSource.Token) + .ContinueWith(delegate{}); // Don't throw on cancellation _logger.LogInformation("Disposing app host"); } @@ -104,8 +116,6 @@ namespace Jellyfin.Server { StartNewInstance(options); } - - return 0; } private static ServerApplicationPaths createApplicationPaths(StartupOptions options) @@ -266,7 +276,10 @@ namespace Jellyfin.Server public static void Shutdown() { - ApplicationTaskCompletionSource.SetResult(true); + if (!_tokenSource.IsCancellationRequested) + { + _tokenSource.Cancel(); + } } public static void Restart()