Use KillTree from Common
This commit is contained in:
parent
73d50bbac3
commit
4df44c8501
|
|
@ -28,4 +28,5 @@ project.lock.json
|
||||||
.testPublish/
|
.testPublish/
|
||||||
.build/
|
.build/
|
||||||
/.vs/
|
/.vs/
|
||||||
|
testWorkDir/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,12 @@ using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.PlatformAbstractions;
|
using Microsoft.Extensions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Watcher.Core.Internal
|
namespace Microsoft.DotNet.Watcher.Core.Internal
|
||||||
{
|
{
|
||||||
public class ProcessWatcher : IProcessWatcher
|
public class ProcessWatcher : IProcessWatcher
|
||||||
{
|
{
|
||||||
private static readonly TimeSpan _processKillTimeout = TimeSpan.FromSeconds(30);
|
|
||||||
|
|
||||||
private Process _runningProcess;
|
private Process _runningProcess;
|
||||||
|
|
||||||
public int Start(string executable, string arguments, string workingDir)
|
public int Start(string executable, string arguments, string workingDir)
|
||||||
|
|
@ -43,7 +41,7 @@ namespace Microsoft.DotNet.Watcher.Core.Internal
|
||||||
{
|
{
|
||||||
if (_runningProcess != null)
|
if (_runningProcess != null)
|
||||||
{
|
{
|
||||||
_runningProcess.KillTree(_processKillTimeout);
|
_runningProcess.KillTree();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using Microsoft.Extensions.PlatformAbstractions;
|
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Watcher.Core.Internal
|
|
||||||
{
|
|
||||||
public static class ProcessExtensions
|
|
||||||
{
|
|
||||||
private static readonly bool _isWindows = PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows;
|
|
||||||
|
|
||||||
public static void KillTree(this Process process, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
string stdout;
|
|
||||||
if (_isWindows)
|
|
||||||
{
|
|
||||||
RunProcessAndWaitForExit(
|
|
||||||
"taskkill",
|
|
||||||
$"/T /F /PID {process.Id}",
|
|
||||||
timeout,
|
|
||||||
out stdout);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var children = GetAllChildIdsUnix(process, timeout);
|
|
||||||
foreach (var childId in children)
|
|
||||||
{
|
|
||||||
KillProcessUnix(childId, timeout);
|
|
||||||
}
|
|
||||||
KillProcessUnix(process.Id, timeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<int> GetAllChildIdsUnix(Process process, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
var children = new HashSet<int>();
|
|
||||||
GetAllChildIdsUnix(process.Id, children, timeout);
|
|
||||||
return children;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void GetAllChildIdsUnix(int parentId, ISet<int> children, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
string stdout;
|
|
||||||
var exitCode = RunProcessAndWaitForExit(
|
|
||||||
"pgrep",
|
|
||||||
$"-P {parentId}",
|
|
||||||
timeout,
|
|
||||||
out stdout);
|
|
||||||
|
|
||||||
if (exitCode == 0 && !string.IsNullOrEmpty(stdout))
|
|
||||||
{
|
|
||||||
using (var reader = new StringReader(stdout))
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
var text = reader.ReadLine();
|
|
||||||
if (text == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int id;
|
|
||||||
if (int.TryParse(text, out id))
|
|
||||||
{
|
|
||||||
children.Add(id);
|
|
||||||
// Recursively get the children
|
|
||||||
GetAllChildIdsUnix(id, children, timeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void KillProcessUnix(int processId, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
string stdout;
|
|
||||||
RunProcessAndWaitForExit(
|
|
||||||
"kill",
|
|
||||||
$"-TERM {processId}",
|
|
||||||
timeout,
|
|
||||||
out stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int RunProcessAndWaitForExit(string fileName, string arguments, TimeSpan timeout, out string stdout)
|
|
||||||
{
|
|
||||||
var startInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = fileName,
|
|
||||||
Arguments = arguments,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
UseShellExecute = false
|
|
||||||
};
|
|
||||||
|
|
||||||
var process = Process.Start(startInfo);
|
|
||||||
|
|
||||||
stdout = null;
|
|
||||||
if (process.WaitForExit((int)timeout.TotalMilliseconds))
|
|
||||||
{
|
|
||||||
stdout = process.StandardOutput.ReadToEnd();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
process.Kill();
|
|
||||||
}
|
|
||||||
|
|
||||||
return process.ExitCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -19,7 +19,10 @@
|
||||||
"Microsoft.Extensions.Logging.Abstractions": "1.0.0-*",
|
"Microsoft.Extensions.Logging.Abstractions": "1.0.0-*",
|
||||||
"Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*",
|
"Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*",
|
||||||
"Microsoft.NETCore.Platforms": "1.0.1-*",
|
"Microsoft.NETCore.Platforms": "1.0.1-*",
|
||||||
"System.Diagnostics.Process": "4.1.0-*"
|
"Microsoft.Extensions.ProcessHelper.Sources": {
|
||||||
|
"type": "build",
|
||||||
|
"version": "1.0.0-*"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"dnxcore50": {
|
"dnxcore50": {
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.DotNet.Watcher.Core.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Watcher.FunctionalTests
|
namespace Microsoft.DotNet.Watcher.FunctionalTests
|
||||||
{
|
{
|
||||||
public class DotNetWatchScenario : IDisposable
|
public class DotNetWatchScenario : IDisposable
|
||||||
{
|
{
|
||||||
private static readonly TimeSpan _processKillTimeout = TimeSpan.FromSeconds(30);
|
|
||||||
|
|
||||||
protected const string DotnetWatch = "dotnet-watch";
|
protected const string DotnetWatch = "dotnet-watch";
|
||||||
|
|
||||||
protected static readonly string _repositoryRoot = FindRepoRoot();
|
protected static readonly string _repositoryRoot = FindRepoRoot();
|
||||||
|
|
@ -38,7 +36,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests
|
||||||
{
|
{
|
||||||
if (!WatcherProcess.HasExited)
|
if (!WatcherProcess.HasExited)
|
||||||
{
|
{
|
||||||
WatcherProcess.KillTree(_processKillTimeout);
|
WatcherProcess.KillTree();
|
||||||
}
|
}
|
||||||
WatcherProcess.Dispose();
|
WatcherProcess.Dispose();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,10 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dotnet-test-xunit": "1.0.0-dev-*",
|
"dotnet-test-xunit": "1.0.0-dev-*",
|
||||||
"Microsoft.Extensions.DependencyInjection": "1.0.0-*",
|
"Microsoft.Extensions.DependencyInjection": "1.0.0-*",
|
||||||
|
"Microsoft.Extensions.ProcessHelper.Sources": {
|
||||||
|
"type": "build",
|
||||||
|
"version": "1.0.0-*"
|
||||||
|
},
|
||||||
"Microsoft.DotNet.Watcher.Core": "1.0.0-*",
|
"Microsoft.DotNet.Watcher.Core": "1.0.0-*",
|
||||||
"Microsoft.NETCore.Platforms": "1.0.1-*",
|
"Microsoft.NETCore.Platforms": "1.0.1-*",
|
||||||
"Newtonsoft.Json": "8.0.2",
|
"Newtonsoft.Json": "8.0.2",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue