diff --git a/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs b/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs
index 7132d539f..993275aa9 100644
--- a/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs
+++ b/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs
@@ -3,6 +3,7 @@ using System.Security.AccessControl;
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 @@ namespace NzbDrone.Common.EnvironmentInfo
{
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 000000000..b61207642
--- /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 162cd5d36..2e2197f52 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 c04ff445f..04cca6527 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 @@ namespace NzbDrone.Common.Processes
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 6f935887f..d67ee5a5e 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 @@ namespace NzbDrone.Console
{
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 @@ namespace NzbDrone.Console
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 99deeef58..39244c28a 100644
--- a/src/NzbDrone.Host/Bootstrap.cs
+++ b/src/NzbDrone.Host/Bootstrap.cs
@@ -4,9 +4,11 @@ using System.Threading;
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 @@ namespace NzbDrone.Host
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;
}
}