Service kills other instances on start.

This commit is contained in:
kayone 2013-11-25 23:08:12 -08:00
parent 1e6817220a
commit d42a63a480
6 changed files with 54 additions and 25 deletions

View File

@ -34,7 +34,7 @@ namespace NzbDrone.App.Test
}); });
Subject.EnforceSingleInstance(); Subject.PreventStartIfAlreadyRunning();
Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Never()); Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Never());
@ -59,7 +59,7 @@ namespace NzbDrone.App.Test
Assert.Throws<TerminateApplicationException>(() => Subject.EnforceSingleInstance()); Assert.Throws<TerminateApplicationException>(() => Subject.PreventStartIfAlreadyRunning());
Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Once()); Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Once());
ExceptionVerification.ExpectedWarns(1); ExceptionVerification.ExpectedWarns(1);
} }
@ -83,7 +83,7 @@ namespace NzbDrone.App.Test
Assert.Throws<TerminateApplicationException>(() => Subject.EnforceSingleInstance()); Assert.Throws<TerminateApplicationException>(() => Subject.PreventStartIfAlreadyRunning());
Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Once()); Mocker.GetMock<IBrowserService>().Verify(c => c.LaunchWebUI(), Times.Once());
ExceptionVerification.ExpectedWarns(1); ExceptionVerification.ExpectedWarns(1);
} }

View File

@ -24,9 +24,9 @@ namespace NzbDrone.Common
Console.WriteLine(); Console.WriteLine();
Console.WriteLine(" Usage: {0} <command> ", Process.GetCurrentProcess().MainModule.ModuleName); Console.WriteLine(" Usage: {0} <command> ", Process.GetCurrentProcess().MainModule.ModuleName);
Console.WriteLine(" Commands:"); Console.WriteLine(" Commands:");
Console.WriteLine(" /{0} Install the application as a Windows Service ({1}).", StartupArguments.INSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME); Console.WriteLine(" /{0} Install the application as a Windows Service ({1}).", StartupContext.INSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
Console.WriteLine(" /{0} Uninstall already installed Windows Service ({1}).", StartupArguments.UNINSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME); Console.WriteLine(" /{0} Uninstall already installed Windows Service ({1}).", StartupContext.UNINSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
Console.WriteLine(" /{0} Don't open NzbDrone in a browser", StartupArguments.NO_BROWSER); Console.WriteLine(" /{0} Don't open NzbDrone in a browser", StartupContext.NO_BROWSER);
Console.WriteLine(" <No Arguments> Run application in console mode."); Console.WriteLine(" <No Arguments> Run application in console mode.");
} }

View File

@ -20,6 +20,7 @@ namespace NzbDrone.Common.Processes
void WaitForExit(Process process); void WaitForExit(Process process);
void SetPriority(int processId, ProcessPriorityClass priority); void SetPriority(int processId, ProcessPriorityClass priority);
void KillAll(string processName); void KillAll(string processName);
void Kill(int processId);
bool Exists(string processName); bool Exists(string processName);
ProcessPriorityClass GetCurrentProcessPriority(); ProcessPriorityClass GetCurrentProcessPriority();
Process Start(string path, string args = null, Action<string> onOutputDataReceived = null, Action<string> onErrorDataReceived = null); Process Start(string path, string args = null, Action<string> onOutputDataReceived = null, Action<string> onErrorDataReceived = null);
@ -254,7 +255,7 @@ namespace NzbDrone.Common.Processes
return process.Modules.Cast<ProcessModule>().FirstOrDefault(module => module.ModuleName.ToLower().EndsWith(".exe")).FileName; return process.Modules.Cast<ProcessModule>().FirstOrDefault(module => module.ModuleName.ToLower().EndsWith(".exe")).FileName;
} }
private void Kill(int processId) public void Kill(int processId)
{ {
var process = Process.GetProcesses().FirstOrDefault(p => p.Id == processId); var process = Process.GetProcesses().FirstOrDefault(p => p.Id == processId);

View File

@ -47,7 +47,7 @@ namespace NzbDrone.Host
} }
catch (TerminateApplicationException e) catch (TerminateApplicationException e)
{ {
Logger.Info("Application has been terminated. Reason " + e.Reason); Logger.Info(e.Message);
} }
} }
@ -56,7 +56,7 @@ namespace NzbDrone.Host
{ {
if (!IsInUtilityMode(applicationModes)) if (!IsInUtilityMode(applicationModes))
{ {
EnsureSingleInstance(); EnsureSingleInstance(applicationModes == ApplicationModes.Service);
} }
DbFactory.RegisterDatabase(_container); DbFactory.RegisterDatabase(_container);
@ -78,9 +78,18 @@ namespace NzbDrone.Host
} }
} }
private static void EnsureSingleInstance() private static void EnsureSingleInstance(bool isService)
{ {
_container.Resolve<ISingleInstancePolicy>().EnforceSingleInstance(); var instancePolicy = _container.Resolve<ISingleInstancePolicy>();
if (isService)
{
instancePolicy.KillAllOtherInstance();
}
else
{
instancePolicy.PreventStartIfAlreadyRunning();
}
} }

View File

@ -1,4 +1,6 @@
using System.Linq; using System;
using System.Collections.Generic;
using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.Processes; using NzbDrone.Common.Processes;
@ -6,7 +8,8 @@ namespace NzbDrone.Host
{ {
public interface ISingleInstancePolicy public interface ISingleInstancePolicy
{ {
void EnforceSingleInstance(); void PreventStartIfAlreadyRunning();
void KillAllOtherInstance();
} }
public class SingleInstancePolicy : ISingleInstancePolicy public class SingleInstancePolicy : ISingleInstancePolicy
@ -22,7 +25,7 @@ namespace NzbDrone.Host
_logger = logger; _logger = logger;
} }
public void EnforceSingleInstance() public void PreventStartIfAlreadyRunning()
{ {
if (IsAlreadyRunning()) if (IsAlreadyRunning())
{ {
@ -32,16 +35,34 @@ namespace NzbDrone.Host
} }
} }
private bool IsAlreadyRunning() public void KillAllOtherInstance()
{ {
var currentId = _processProvider.GetCurrentProcess().Id; foreach (var processId in GetOtherNzbDroneProcessIds())
var consoleIds = _processProvider.FindProcessByName(ProcessProvider.NZB_DRONE_CONSOLE_PROCESS_NAME).Select(c => c.Id); {
var guiIds = _processProvider.FindProcessByName(ProcessProvider.NZB_DRONE_PROCESS_NAME).Select(c => c.Id); _processProvider.Kill(processId);
}
var otherProcesses = consoleIds.Union(guiIds).Except(new[] { currentId });
return otherProcesses.Any();
} }
private bool IsAlreadyRunning()
{
return GetOtherNzbDroneProcessIds().Any();
}
private List<int> GetOtherNzbDroneProcessIds()
{
var currentId = _processProvider.GetCurrentProcess().Id;
var consoleIds = _processProvider.FindProcessByName(ProcessProvider.NZB_DRONE_CONSOLE_PROCESS_NAME)
.Select(c => c.Id);
var winformIds = _processProvider.FindProcessByName(ProcessProvider.NZB_DRONE_PROCESS_NAME).Select(c => c.Id);
var otherProcesses = consoleIds.Union(winformIds).Except(new[] { currentId }).ToList();
if (otherProcesses.Any())
{
_logger.Info("{0} instance(s) of NzbDrone are running", otherProcesses.Count);
}
return otherProcesses;
}
} }
} }

View File

@ -5,10 +5,8 @@ namespace NzbDrone.Host
public class TerminateApplicationException : ApplicationException public class TerminateApplicationException : ApplicationException
{ {
public TerminateApplicationException(string reason) public TerminateApplicationException(string reason)
: base("Application is being terminated. Reason : " + reason)
{ {
Reason = reason;
} }
public string Reason { get; private set; }
} }
} }