Service kills other instances on start.
This commit is contained in:
parent
1e6817220a
commit
d42a63a480
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue