Kill NzbDrone process if service couldn't be stopped.
better Process/Service handling.
This commit is contained in:
parent
6e3aef8ab2
commit
c1a75604fd
|
@ -1,4 +1,5 @@
|
||||||
using System.ServiceProcess;
|
using System;
|
||||||
|
using System.ServiceProcess;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
@ -16,23 +17,28 @@ namespace NzbDrone.Common.Test
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
WindowsOnly();
|
WindowsOnly();
|
||||||
|
CleanupService();
|
||||||
|
|
||||||
if (Subject.ServiceExist(TEMP_SERVICE_NAME))
|
|
||||||
{
|
|
||||||
Subject.UnInstall(TEMP_SERVICE_NAME);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[TearDown]
|
[TearDown]
|
||||||
public void TearDown()
|
public void TearDown()
|
||||||
{
|
{
|
||||||
WindowsOnly();
|
WindowsOnly();
|
||||||
|
CleanupService();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void CleanupService()
|
||||||
|
{
|
||||||
if (Subject.ServiceExist(TEMP_SERVICE_NAME))
|
if (Subject.ServiceExist(TEMP_SERVICE_NAME))
|
||||||
{
|
{
|
||||||
Subject.UnInstall(TEMP_SERVICE_NAME);
|
Subject.UnInstall(TEMP_SERVICE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Subject.IsServiceRunning(ALWAYS_INSTALLED_SERVICE))
|
||||||
|
{
|
||||||
|
Subject.Stop(ALWAYS_INSTALLED_SERVICE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -86,6 +92,19 @@ namespace NzbDrone.Common.Test
|
||||||
.Should().Be(ServiceControllerStatus.Stopped);
|
.Should().Be(ServiceControllerStatus.Stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_throw_if_starting_a_running_serivce()
|
||||||
|
{
|
||||||
|
Subject.GetService(ALWAYS_INSTALLED_SERVICE).Status
|
||||||
|
.Should().NotBe(ServiceControllerStatus.Running);
|
||||||
|
|
||||||
|
Subject.Start(ALWAYS_INSTALLED_SERVICE);
|
||||||
|
Assert.Throws<InvalidOperationException>(() => Subject.Start(ALWAYS_INSTALLED_SERVICE));
|
||||||
|
|
||||||
|
|
||||||
|
ExceptionVerification.ExpectedWarns(1);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Should_log_warn_if_on_stop_if_service_is_already_stopped()
|
public void Should_log_warn_if_on_stop_if_service_is_already_stopped()
|
||||||
{
|
{
|
||||||
|
|
|
@ -148,14 +148,14 @@
|
||||||
<Compile Include="Contract\ParseErrorReport.cs" />
|
<Compile Include="Contract\ParseErrorReport.cs" />
|
||||||
<Compile Include="Model\AuthenticationType.cs" />
|
<Compile Include="Model\AuthenticationType.cs" />
|
||||||
<Compile Include="PathExtensions.cs" />
|
<Compile Include="PathExtensions.cs" />
|
||||||
<Compile Include="IDiskProvider.cs" />
|
<Compile Include="DiskProvider.cs" />
|
||||||
<Compile Include="EnvironmentInfo\AppFolderInfo.cs" />
|
<Compile Include="EnvironmentInfo\AppFolderInfo.cs" />
|
||||||
<Compile Include="Model\ProcessInfo.cs" />
|
<Compile Include="Model\ProcessInfo.cs" />
|
||||||
<Compile Include="IProcessProvider.cs" />
|
<Compile Include="ProcessProvider.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Properties\SharedAssemblyInfo.cs" />
|
<Compile Include="Properties\SharedAssemblyInfo.cs" />
|
||||||
<Compile Include="RestProvider.cs" />
|
<Compile Include="RestProvider.cs" />
|
||||||
<Compile Include="IServiceProvider.cs" />
|
<Compile Include="ServiceProvider.cs" />
|
||||||
<Compile Include="TinyIoC.cs" />
|
<Compile Include="TinyIoC.cs" />
|
||||||
<Compile Include="TryParseExtension.cs" />
|
<Compile Include="TryParseExtension.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
@ -12,10 +11,9 @@ namespace NzbDrone.Common
|
||||||
ProcessInfo GetCurrentProcess();
|
ProcessInfo GetCurrentProcess();
|
||||||
ProcessInfo GetProcessById(int id);
|
ProcessInfo GetProcessById(int id);
|
||||||
IEnumerable<ProcessInfo> GetProcessByName(string name);
|
IEnumerable<ProcessInfo> GetProcessByName(string name);
|
||||||
void Start(string path);
|
Process Start(string path);
|
||||||
Process Start(ProcessStartInfo startInfo);
|
Process Start(ProcessStartInfo startInfo);
|
||||||
void WaitForExit(Process process);
|
void WaitForExit(Process process);
|
||||||
void Kill(int processId);
|
|
||||||
void SetPriority(int processId, ProcessPriorityClass priority);
|
void SetPriority(int processId, ProcessPriorityClass priority);
|
||||||
void KillAll(string processName);
|
void KillAll(string processName);
|
||||||
}
|
}
|
||||||
|
@ -27,12 +25,12 @@ namespace NzbDrone.Common
|
||||||
public const string NzbDroneProcessName = "NzbDrone";
|
public const string NzbDroneProcessName = "NzbDrone";
|
||||||
public const string NzbDroneConsoleProcessName = "NzbDrone.Console";
|
public const string NzbDroneConsoleProcessName = "NzbDrone.Console";
|
||||||
|
|
||||||
public ProcessInfo GetCurrentProcess()
|
public ProcessInfo GetCurrentProcess()
|
||||||
{
|
{
|
||||||
return ConvertToProcessInfo(Process.GetCurrentProcess());
|
return ConvertToProcessInfo(Process.GetCurrentProcess());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProcessInfo GetProcessById(int id)
|
public ProcessInfo GetProcessById(int id)
|
||||||
{
|
{
|
||||||
Logger.Trace("Finding process with Id:{0}", id);
|
Logger.Trace("Finding process with Id:{0}", id);
|
||||||
|
|
||||||
|
@ -50,17 +48,17 @@ namespace NzbDrone.Common
|
||||||
return processInfo;
|
return processInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ProcessInfo> GetProcessByName(string name)
|
public IEnumerable<ProcessInfo> GetProcessByName(string name)
|
||||||
{
|
{
|
||||||
return Process.GetProcessesByName(name).Select(ConvertToProcessInfo).Where(p => p != null);
|
return Process.GetProcessesByName(name).Select(ConvertToProcessInfo).Where(p => p != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start(string path)
|
public Process Start(string path)
|
||||||
{
|
{
|
||||||
Process.Start(path);
|
return Start(new ProcessStartInfo(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Process Start(ProcessStartInfo startInfo)
|
public Process Start(ProcessStartInfo startInfo)
|
||||||
{
|
{
|
||||||
Logger.Info("Starting process. [{0}]", startInfo.FileName);
|
Logger.Info("Starting process. [{0}]", startInfo.FileName);
|
||||||
|
|
||||||
|
@ -69,38 +67,19 @@ namespace NzbDrone.Common
|
||||||
StartInfo = startInfo
|
StartInfo = startInfo
|
||||||
};
|
};
|
||||||
process.Start();
|
process.Start();
|
||||||
|
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WaitForExit(Process process)
|
public void WaitForExit(Process process)
|
||||||
{
|
{
|
||||||
Logger.Trace("Waiting for process {0} to exit.", process.ProcessName);
|
Logger.Trace("Waiting for process {0} to exit.", process.ProcessName);
|
||||||
process.WaitForExit();
|
process.WaitForExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Kill(int processId)
|
|
||||||
{
|
|
||||||
if (processId == 0 || Process.GetProcesses().All(p => p.Id != processId))
|
|
||||||
{
|
|
||||||
Logger.Warn("Cannot find process with id: {0}", processId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var process = Process.GetProcessById(processId);
|
|
||||||
|
|
||||||
if (process.HasExited)
|
public void SetPriority(int processId, ProcessPriorityClass priority)
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Info("[{0}]: Killing process", process.Id);
|
|
||||||
process.Kill();
|
|
||||||
Logger.Info("[{0}]: Waiting for exit", process.Id);
|
|
||||||
process.WaitForExit();
|
|
||||||
Logger.Info("[{0}]: Process terminated successfully", process.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetPriority(int processId, ProcessPriorityClass priority)
|
|
||||||
{
|
{
|
||||||
var process = Process.GetProcessById(processId);
|
var process = Process.GetProcessById(processId);
|
||||||
|
|
||||||
|
@ -125,7 +104,7 @@ namespace NzbDrone.Common
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void KillAll(string processName)
|
public void KillAll(string processName)
|
||||||
{
|
{
|
||||||
var processToKill = GetProcessByName(processName);
|
var processToKill = GetProcessByName(processName);
|
||||||
|
|
||||||
|
@ -134,5 +113,27 @@ namespace NzbDrone.Common
|
||||||
Kill(processInfo.Id);
|
Kill(processInfo.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Kill(int processId)
|
||||||
|
{
|
||||||
|
if (processId == 0 || Process.GetProcesses().All(p => p.Id != processId))
|
||||||
|
{
|
||||||
|
Logger.Warn("Cannot find process with id: {0}", processId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var process = Process.GetProcessById(processId);
|
||||||
|
|
||||||
|
if (process.HasExited)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Info("[{0}]: Killing process", process.Id);
|
||||||
|
process.Kill();
|
||||||
|
Logger.Info("[{0}]: Waiting for exit", process.Id);
|
||||||
|
process.WaitForExit();
|
||||||
|
Logger.Info("[{0}]: Process terminated successfully", process.Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -41,7 +41,11 @@ namespace NzbDrone.Common
|
||||||
var service = ServiceController.GetServices()
|
var service = ServiceController.GetServices()
|
||||||
.SingleOrDefault(s => String.Equals(s.ServiceName, name, StringComparison.InvariantCultureIgnoreCase));
|
.SingleOrDefault(s => String.Equals(s.ServiceName, name, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
|
||||||
return service != null && (service.Status == ServiceControllerStatus.Running || service.Status == ServiceControllerStatus.StartPending);
|
return service != null && (
|
||||||
|
service.Status != ServiceControllerStatus.Stopped ||
|
||||||
|
service.Status == ServiceControllerStatus.StopPending ||
|
||||||
|
service.Status == ServiceControllerStatus.Paused ||
|
||||||
|
service.Status == ServiceControllerStatus.PausePending);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Install(string serviceName)
|
public virtual void Install(string serviceName)
|
|
@ -33,12 +33,13 @@ namespace NzbDrone.Update.UpdateEngine
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_logger.Info("NzbDrone Service is installed and running");
|
||||||
_serviceProvider.Stop(ServiceProvider.NZBDRONE_SERVICE_NAME);
|
_serviceProvider.Stop(ServiceProvider.NZBDRONE_SERVICE_NAME);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.WarnException("couldn't stop service", e);
|
_logger.ErrorException("couldn't stop service", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue