Updater will stop process by ID on mono

This commit is contained in:
Mark McDowall 2014-05-24 12:06:32 -07:00
parent 198e7cc2f7
commit fe8555d3ea
6 changed files with 72 additions and 20 deletions

View File

@ -21,6 +21,7 @@ namespace NzbDrone.Common.Processes
void SetPriority(int processId, ProcessPriorityClass priority); void SetPriority(int processId, ProcessPriorityClass priority);
void KillAll(string processName); void KillAll(string processName);
void Kill(int processId); void Kill(int processId);
Boolean Exists(int processId);
Boolean Exists(string processName); Boolean 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);
@ -40,6 +41,11 @@ namespace NzbDrone.Common.Processes
return ConvertToProcessInfo(Process.GetCurrentProcess()); return ConvertToProcessInfo(Process.GetCurrentProcess());
} }
public bool Exists(int processId)
{
return GetProcessById(processId) != null;
}
public Boolean Exists(string processName) public Boolean Exists(string processName)
{ {
return GetProcessesByName(processName).Any(); return GetProcessesByName(processName).Any();

View File

@ -2,9 +2,9 @@
using System.IO; using System.IO;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Processes;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
using NzbDrone.Update.UpdateEngine; using NzbDrone.Update.UpdateEngine;
@ -13,11 +13,28 @@ namespace NzbDrone.Update.Test
[TestFixture] [TestFixture]
public class InstallUpdateServiceFixture : TestBase<InstallUpdateService> public class InstallUpdateServiceFixture : TestBase<InstallUpdateService>
{ {
private string _targetFolder = @"C:\NzbDrone\".AsOsAgnostic();
private const int _processId = 12;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
Mocker.GetMock<IAppFolderInfo>() Mocker.GetMock<IAppFolderInfo>()
.Setup(c => c.TempFolder).Returns(@"C:\Temp\"); .Setup(c => c.TempFolder).Returns(@"C:\Temp\");
}
private void GivenTargetFolderExists()
{
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.FolderExists(_targetFolder))
.Returns(true);
}
private void GivenProcessExists()
{
Mocker.GetMock<IProcessProvider>()
.Setup(c => c.Exists(_processId))
.Returns(true);
} }
[TestCase(null)] [TestCase(null)]
@ -25,16 +42,14 @@ namespace NzbDrone.Update.Test
[TestCase(" ")] [TestCase(" ")]
public void update_should_throw_target_folder_is_blank(string target) public void update_should_throw_target_folder_is_blank(string target)
{ {
Assert.Throws<ArgumentException>(() => Subject.Start(target)) Assert.Throws<ArgumentException>(() => Subject.Start(target, _processId))
.Message.Should().StartWith("Target folder can not be null or empty"); .Message.Should().StartWith("Target folder can not be null or empty");
} }
[Test] [Test]
public void update_should_throw_if_target_folder_doesnt_exist() public void update_should_throw_if_target_folder_doesnt_exist()
{ {
string targetFolder = "c:\\NzbDrone\\"; Assert.Throws<DirectoryNotFoundException>(() => Subject.Start(_targetFolder, _processId))
Assert.Throws<DirectoryNotFoundException>(() => Subject.Start(targetFolder))
.Message.Should().StartWith("Target folder doesn't exist"); .Message.Should().StartWith("Target folder doesn't exist");
} }
@ -42,18 +57,34 @@ namespace NzbDrone.Update.Test
public void update_should_throw_if_update_folder_doesnt_exist() public void update_should_throw_if_update_folder_doesnt_exist()
{ {
const string sandboxFolder = @"C:\Temp\NzbDrone_update\nzbdrone"; const string sandboxFolder = @"C:\Temp\NzbDrone_update\nzbdrone";
const string targetFolder = "c:\\NzbDrone\\";
Mocker.GetMock<IDiskProvider>() GivenTargetFolderExists();
.Setup(c => c.FolderExists(targetFolder)) GivenProcessExists();
.Returns(true);
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(c => c.FolderExists(sandboxFolder)) .Setup(c => c.FolderExists(sandboxFolder))
.Returns(false); .Returns(false);
Assert.Throws<DirectoryNotFoundException>(() => Subject.Start(targetFolder)) Assert.Throws<DirectoryNotFoundException>(() => Subject.Start(_targetFolder, _processId))
.Message.Should().StartWith("Update folder doesn't exist"); .Message.Should().StartWith("Update folder doesn't exist");
} }
[Test]
public void update_should_throw_if_process_is_zero()
{
GivenTargetFolderExists();
Assert.Throws<ArgumentException>(() => Subject.Start(_targetFolder, 0))
.Message.Should().StartWith("Invalid process ID");
}
[Test]
public void update_should_throw_if_process_id_doesnt_exist()
{
GivenTargetFolderExists();
Assert.Throws<ArgumentException>(() => Subject.Start(_targetFolder, _processId))
.Message.Should().StartWith("Process with ID doesn't exist");
}
} }
} }

View File

@ -43,7 +43,7 @@ namespace NzbDrone.Update.Test
Subject.Start(new[] { "12", "" }); Subject.Start(new[] { "12", "" });
Mocker.GetMock<IInstallUpdateService>().Verify(c => c.Start(@"C:\NzbDrone"), Times.Once()); Mocker.GetMock<IInstallUpdateService>().Verify(c => c.Start(@"C:\NzbDrone", 12), Times.Once());
} }

View File

@ -68,7 +68,7 @@ namespace NzbDrone.Update
} }
logger.Info("Starting update process. Target Path:{0}", targetFolder); logger.Info("Starting update process. Target Path:{0}", targetFolder);
_installUpdateService.Start(targetFolder); _installUpdateService.Start(targetFolder, startupContext.ProcessId);
} }
private UpdateStartupContext ParseArgs(string[] args) private UpdateStartupContext ParseArgs(string[] args)

View File

@ -4,12 +4,13 @@ using NLog;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Processes;
namespace NzbDrone.Update.UpdateEngine namespace NzbDrone.Update.UpdateEngine
{ {
public interface IInstallUpdateService public interface IInstallUpdateService
{ {
void Start(string installationFolder); void Start(string installationFolder, int processId);
} }
public class InstallUpdateService : IInstallUpdateService public class InstallUpdateService : IInstallUpdateService
@ -21,6 +22,7 @@ namespace NzbDrone.Update.UpdateEngine
private readonly IBackupAndRestore _backupAndRestore; private readonly IBackupAndRestore _backupAndRestore;
private readonly IBackupAppData _backupAppData; private readonly IBackupAppData _backupAppData;
private readonly IStartNzbDrone _startNzbDrone; private readonly IStartNzbDrone _startNzbDrone;
private readonly IProcessProvider _processProvider;
private readonly Logger _logger; private readonly Logger _logger;
public InstallUpdateService(IDiskProvider diskProvider, public InstallUpdateService(IDiskProvider diskProvider,
@ -30,6 +32,7 @@ namespace NzbDrone.Update.UpdateEngine
IBackupAndRestore backupAndRestore, IBackupAndRestore backupAndRestore,
IBackupAppData backupAppData, IBackupAppData backupAppData,
IStartNzbDrone startNzbDrone, IStartNzbDrone startNzbDrone,
IProcessProvider processProvider,
Logger logger) Logger logger)
{ {
_diskProvider = diskProvider; _diskProvider = diskProvider;
@ -39,10 +42,11 @@ namespace NzbDrone.Update.UpdateEngine
_backupAndRestore = backupAndRestore; _backupAndRestore = backupAndRestore;
_backupAppData = backupAppData; _backupAppData = backupAppData;
_startNzbDrone = startNzbDrone; _startNzbDrone = startNzbDrone;
_processProvider = processProvider;
_logger = logger; _logger = logger;
} }
private void Verify(string targetFolder) private void Verify(string targetFolder, int processId)
{ {
_logger.Info("Verifying requirements before update..."); _logger.Info("Verifying requirements before update...");
@ -52,20 +56,30 @@ namespace NzbDrone.Update.UpdateEngine
if (!_diskProvider.FolderExists(targetFolder)) if (!_diskProvider.FolderExists(targetFolder))
throw new DirectoryNotFoundException("Target folder doesn't exist " + targetFolder); throw new DirectoryNotFoundException("Target folder doesn't exist " + targetFolder);
if (processId < 1)
{
throw new ArgumentException("Invalid process ID: " + processId);
}
if (!_processProvider.Exists(processId))
{
throw new ArgumentException("Process with ID doesn't exist " + processId);
}
_logger.Info("Verifying Update Folder"); _logger.Info("Verifying Update Folder");
if (!_diskProvider.FolderExists(_appFolderInfo.GetUpdatePackageFolder())) if (!_diskProvider.FolderExists(_appFolderInfo.GetUpdatePackageFolder()))
throw new DirectoryNotFoundException("Update folder doesn't exist " + _appFolderInfo.GetUpdatePackageFolder()); throw new DirectoryNotFoundException("Update folder doesn't exist " + _appFolderInfo.GetUpdatePackageFolder());
} }
public void Start(string installationFolder) public void Start(string installationFolder, int processId)
{ {
Verify(installationFolder); Verify(installationFolder, processId);
var appType = _detectApplicationType.GetAppType(); var appType = _detectApplicationType.GetAppType();
try try
{ {
_terminateNzbDrone.Terminate(); _terminateNzbDrone.Terminate(processId);
_backupAndRestore.Backup(installationFolder); _backupAndRestore.Backup(installationFolder);
_backupAppData.Backup(); _backupAppData.Backup();

View File

@ -9,7 +9,7 @@ namespace NzbDrone.Update.UpdateEngine
{ {
public interface ITerminateNzbDrone public interface ITerminateNzbDrone
{ {
void Terminate(); void Terminate(int processId);
} }
public class TerminateNzbDrone : ITerminateNzbDrone public class TerminateNzbDrone : ITerminateNzbDrone
@ -25,11 +25,12 @@ namespace NzbDrone.Update.UpdateEngine
_logger = logger; _logger = logger;
} }
public void Terminate() public void Terminate(int processId)
{ {
if (OsInfo.IsMono) if (OsInfo.IsMono)
{ {
_logger.Info("Stopping all instances"); _logger.Info("Stopping all instances");
_processProvider.Kill(processId);
_processProvider.KillAll(ProcessProvider.NZB_DRONE_CONSOLE_PROCESS_NAME); _processProvider.KillAll(ProcessProvider.NZB_DRONE_CONSOLE_PROCESS_NAME);
_processProvider.KillAll(ProcessProvider.NZB_DRONE_PROCESS_NAME); _processProvider.KillAll(ProcessProvider.NZB_DRONE_PROCESS_NAME);