diff --git a/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs b/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs
index 7132d539fd..993275aa95 100644
--- a/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs
+++ b/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs
@@ -3,6 +3,7 @@
using System.Security.Principal;
using NLog;
using NzbDrone.Common.Disk;
+using NzbDrone.Common.Exceptions;
using NzbDrone.Common.Instrumentation;
namespace NzbDrone.Common.EnvironmentInfo
@@ -33,6 +34,11 @@ public void Register()
{
SetPermissions();
}
+
+ if (!_diskProvider.FolderWritable(_appFolderInfo.AppDataFolder))
+ {
+ throw new SonarrStartupException("AppFolder {0} is not writable", _appFolderInfo.AppDataFolder);
+ }
}
private void SetPermissions()
diff --git a/src/NzbDrone.Common/Exceptions/SonarrStartupException.cs b/src/NzbDrone.Common/Exceptions/SonarrStartupException.cs
new file mode 100644
index 0000000000..b612076425
--- /dev/null
+++ b/src/NzbDrone.Common/Exceptions/SonarrStartupException.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace NzbDrone.Common.Exceptions
+{
+ public class SonarrStartupException : NzbDroneException
+ {
+ public SonarrStartupException(string message, params object[] args)
+ : base("Sonarr failed to start: " + string.Format(message, args))
+ {
+
+ }
+
+ public SonarrStartupException(string message)
+ : base("Sonarr failed to start: " + message)
+ {
+
+ }
+
+ public SonarrStartupException()
+ : base("Sonarr failed to start")
+ {
+
+ }
+
+ public SonarrStartupException(Exception innerException, string message, params object[] args)
+ : base("Sonarr failed to start: " + string.Format(message, args), innerException)
+ {
+ }
+
+ public SonarrStartupException(Exception innerException, string message)
+ : base("Sonarr failed to start: " + message, innerException)
+ {
+ }
+
+ public SonarrStartupException(Exception innerException)
+ : base("Sonarr failed to start: " + innerException.Message)
+ {
+
+ }
+ }
+}
diff --git a/src/NzbDrone.Common/NzbDrone.Common.csproj b/src/NzbDrone.Common/NzbDrone.Common.csproj
index 162cd5d360..2e2197f52d 100644
--- a/src/NzbDrone.Common/NzbDrone.Common.csproj
+++ b/src/NzbDrone.Common/NzbDrone.Common.csproj
@@ -92,6 +92,7 @@
+
diff --git a/src/NzbDrone.Common/Processes/PidFileProvider.cs b/src/NzbDrone.Common/Processes/PidFileProvider.cs
index c04ff445fa..04cca65279 100644
--- a/src/NzbDrone.Common/Processes/PidFileProvider.cs
+++ b/src/NzbDrone.Common/Processes/PidFileProvider.cs
@@ -2,6 +2,7 @@
using System.IO;
using NLog;
using NzbDrone.Common.EnvironmentInfo;
+using NzbDrone.Common.Exceptions;
namespace NzbDrone.Common.Processes
{
@@ -38,7 +39,7 @@ public void Write()
catch (Exception ex)
{
_logger.Error(ex, "Unable to write PID file {0}", filename);
- throw;
+ throw new SonarrStartupException(ex, "Unable to write PID file {0}", filename);
}
}
}
diff --git a/src/NzbDrone.Console/ConsoleApp.cs b/src/NzbDrone.Console/ConsoleApp.cs
index 6f935887f6..d67ee5a5e4 100644
--- a/src/NzbDrone.Console/ConsoleApp.cs
+++ b/src/NzbDrone.Console/ConsoleApp.cs
@@ -2,6 +2,7 @@
using System.Net.Sockets;
using NLog;
using NzbDrone.Common.EnvironmentInfo;
+using NzbDrone.Common.Exceptions;
using NzbDrone.Common.Instrumentation;
using NzbDrone.Host;
@@ -11,6 +12,14 @@ public static class ConsoleApp
{
private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(ConsoleApp));
+ private enum ExitCodes : int
+ {
+ Normal = 0,
+ UnknownFailure = 1,
+ RecoverableFailure = 2,
+ NonRecoverableFailure = 3
+ }
+
public static void Main(string[] args)
{
try
@@ -19,30 +28,61 @@ public static void Main(string[] args)
NzbDroneLogger.Register(startupArgs, false, true);
Bootstrap.Start(startupArgs, new ConsoleAlerts());
}
- catch (SocketException exception)
+ catch (SonarrStartupException ex)
{
System.Console.WriteLine("");
System.Console.WriteLine("");
- Logger.Fatal(exception.Message + ". This can happen if another instance of Sonarr is already running another application is using the same port (default: 8989) or the user has insufficient permissions");
- System.Console.WriteLine("Press enter to exit...");
- System.Console.ReadLine();
- Environment.Exit(1);
+ Logger.Fatal(ex, "EPIC FAIL!");
+ Exit(ExitCodes.NonRecoverableFailure);
}
- catch (Exception e)
+ catch (SocketException ex)
{
System.Console.WriteLine("");
System.Console.WriteLine("");
- Logger.Fatal(e, "EPIC FAIL!");
- System.Console.WriteLine("Press enter to exit...");
- System.Console.ReadLine();
- Environment.Exit(1);
+ Logger.Fatal(ex.Message + ". This can happen if another instance of Sonarr is already running another application is using the same port (default: 8989) or the user has insufficient permissions");
+ Exit(ExitCodes.RecoverableFailure);
+ }
+ catch (Exception ex)
+ {
+ System.Console.WriteLine("");
+ System.Console.WriteLine("");
+ Logger.Fatal(ex, "EPIC FAIL!");
+ Exit(ExitCodes.UnknownFailure);
}
Logger.Info("Exiting main.");
+ Exit(ExitCodes.Normal);
+ }
+
+ private static void Exit(ExitCodes exitCode)
+ {
+ LogManager.Flush();
+
+ if (exitCode != ExitCodes.Normal)
+ {
+ System.Console.WriteLine("Press enter to exit...");
+
+ System.Threading.Thread.Sleep(1000);
+
+ if (exitCode == ExitCodes.NonRecoverableFailure)
+ {
+ System.Console.WriteLine("Non-recoverable failure, waiting for user intervention...");
+ for (int i = 0; i < 3600; i++)
+ {
+ System.Threading.Thread.Sleep(1000);
+
+ if (System.Console.KeyAvailable) break;
+ }
+ }
+
+ // Please note that ReadLine silently succeeds if there is no console, KeyAvailable does not.
+ System.Console.ReadLine();
+ }
+
//Need this to terminate on mono (thanks nlog)
LogManager.Configuration = null;
- Environment.Exit(0);
+ Environment.Exit((int)exitCode);
}
}
}
diff --git a/src/NzbDrone.Host/Bootstrap.cs b/src/NzbDrone.Host/Bootstrap.cs
index 99deeef582..39244c28ae 100644
--- a/src/NzbDrone.Host/Bootstrap.cs
+++ b/src/NzbDrone.Host/Bootstrap.cs
@@ -4,9 +4,11 @@
using NLog;
using NzbDrone.Common.Composition;
using NzbDrone.Common.EnvironmentInfo;
+using NzbDrone.Common.Exceptions;
using NzbDrone.Common.Instrumentation;
using NzbDrone.Common.Processes;
using NzbDrone.Common.Security;
+using NzbDrone.Core.Configuration;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Instrumentation;
@@ -49,9 +51,13 @@ public static void Start(StartupContext startupContext, IUserAlert userAlert, Ac
SpinToExit(appMode);
}
}
- catch (TerminateApplicationException e)
+ catch (InvalidConfigFileException ex)
{
- Logger.Info(e.Message);
+ throw new SonarrStartupException(ex);
+ }
+ catch (TerminateApplicationException ex)
+ {
+ Logger.Info(ex.Message);
LogManager.Configuration = null;
}
}