diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj
index efdb75f980..c834648a5f 100644
--- a/Jellyfin.Server/Jellyfin.Server.csproj
+++ b/Jellyfin.Server/Jellyfin.Server.csproj
@@ -9,9 +9,8 @@
-
- latest
true
+ enable
diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs
index e8bd0cd309..887283d2a4 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
+using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
@@ -21,6 +22,7 @@ using MediaBrowser.Model.Globalization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
using Serilog;
using Serilog.Extensions.Logging;
using SQLitePCL;
@@ -35,7 +37,7 @@ namespace Jellyfin.Server
{
private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory();
- private static ILogger _logger;
+ private static ILogger _logger = NullLogger.Instance;
private static bool _restartOnShutdown;
///
@@ -86,6 +88,12 @@ namespace Jellyfin.Server
{
var stopWatch = new Stopwatch();
stopWatch.Start();
+
+ // Log all uncaught exception to std error
+ static void UnhandledExceptionToConsole(object sender, UnhandledExceptionEventArgs e) =>
+ Console.Error.WriteLine("Unhandled Exception\n" + e.ExceptionObject.ToString());
+ AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionToConsole;
+
ServerApplicationPaths appPaths = CreateApplicationPaths(options);
// $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
@@ -97,6 +105,8 @@ namespace Jellyfin.Server
_logger = _loggerFactory.CreateLogger("Main");
+ // Log uncaught exceptions to the logging instead of std error
+ AppDomain.CurrentDomain.UnhandledException -= UnhandledExceptionToConsole;
AppDomain.CurrentDomain.UnhandledException += (sender, e)
=> _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception");
@@ -129,7 +139,7 @@ namespace Jellyfin.Server
_logger.LogInformation(
"Jellyfin version: {Version}",
- Assembly.GetEntryAssembly().GetName().Version.ToString(3));
+ Assembly.GetEntryAssembly()!.GetName().Version!.ToString(3));
ApplicationHost.LogEnvironmentInfo(_logger, appPaths);
@@ -361,16 +371,25 @@ namespace Jellyfin.Server
private static async Task CreateConfiguration(IApplicationPaths appPaths)
{
+ const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json";
string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json");
if (!File.Exists(configPath))
{
// For some reason the csproj name is used instead of the assembly name
- using (Stream rscstr = typeof(Program).Assembly
- .GetManifestResourceStream("Jellyfin.Server.Resources.Configuration.logging.json"))
- using (Stream fstr = File.Open(configPath, FileMode.CreateNew))
+ using (Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath))
{
- await rscstr.CopyToAsync(fstr).ConfigureAwait(false);
+ if (resource == null)
+ {
+ throw new InvalidOperationException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "Invalid resource path: '{0}'",
+ ResourcePath));
+ }
+
+ using Stream dst = File.Open(configPath, FileMode.CreateNew);
+ await resource.CopyToAsync(dst).ConfigureAwait(false);
}
}
@@ -433,7 +452,7 @@ namespace Jellyfin.Server
{
_logger.LogInformation("Starting new instance");
- string module = options.RestartPath;
+ var module = options.RestartPath;
if (string.IsNullOrWhiteSpace(module))
{
@@ -441,7 +460,6 @@ namespace Jellyfin.Server
}
string commandLineArgsString;
-
if (options.RestartArgs != null)
{
commandLineArgsString = options.RestartArgs ?? string.Empty;
diff --git a/Jellyfin.Server/StartupOptions.cs b/Jellyfin.Server/StartupOptions.cs
index bb0adaf630..1fb1c5af8e 100644
--- a/Jellyfin.Server/StartupOptions.cs
+++ b/Jellyfin.Server/StartupOptions.cs
@@ -13,39 +13,39 @@ namespace Jellyfin.Server
///
/// The path to the data directory.
[Option('d', "datadir", Required = false, HelpText = "Path to use for the data folder (database files, etc.).")]
- public string DataDir { get; set; }
+ public string? DataDir { get; set; }
///
/// Gets or sets the path to the web directory.
///
/// The path to the web directory.
[Option('w', "webdir", Required = false, HelpText = "Path to the Jellyfin web UI resources.")]
- public string WebDir { get; set; }
+ public string? WebDir { get; set; }
///
/// Gets or sets the path to the cache directory.
///
/// The path to the cache directory.
[Option('C', "cachedir", Required = false, HelpText = "Path to use for caching.")]
- public string CacheDir { get; set; }
+ public string? CacheDir { get; set; }
///
/// Gets or sets the path to the config directory.
///
/// The path to the config directory.
[Option('c', "configdir", Required = false, HelpText = "Path to use for configuration data (user settings and pictures).")]
- public string ConfigDir { get; set; }
+ public string? ConfigDir { get; set; }
///
/// Gets or sets the path to the log directory.
///
/// The path to the log directory.
[Option('l', "logdir", Required = false, HelpText = "Path to use for writing log files.")]
- public string LogDir { get; set; }
+ public string? LogDir { get; set; }
///
[Option("ffmpeg", Required = false, HelpText = "Path to external FFmpeg executable to use in place of default found in PATH.")]
- public string FFmpegPath { get; set; }
+ public string? FFmpegPath { get; set; }
///
[Option("service", Required = false, HelpText = "Run as headless service.")]
@@ -57,14 +57,14 @@ namespace Jellyfin.Server
///
[Option("package-name", Required = false, HelpText = "Used when packaging Jellyfin (example, synology).")]
- public string PackageName { get; set; }
+ public string? PackageName { get; set; }
///
[Option("restartpath", Required = false, HelpText = "Path to restart script.")]
- public string RestartPath { get; set; }
+ public string? RestartPath { get; set; }
///
[Option("restartargs", Required = false, HelpText = "Arguments for restart script.")]
- public string RestartArgs { get; set; }
+ public string? RestartArgs { get; set; }
}
}
diff --git a/jellyfin.ruleset b/jellyfin.ruleset
index e259131b05..2c3930a28a 100644
--- a/jellyfin.ruleset
+++ b/jellyfin.ruleset
@@ -6,6 +6,8 @@
+
+