Use KillTree from Common
This commit is contained in:
parent
73d50bbac3
commit
4df44c8501
|
|
@ -28,4 +28,5 @@ project.lock.json
|
|||
.testPublish/
|
||||
.build/
|
||||
/.vs/
|
||||
testWorkDir/
|
||||
|
||||
|
|
|
|||
|
|
@ -5,14 +5,12 @@ using System;
|
|||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.DotNet.Watcher.Core.Internal
|
||||
{
|
||||
public class ProcessWatcher : IProcessWatcher
|
||||
{
|
||||
private static readonly TimeSpan _processKillTimeout = TimeSpan.FromSeconds(30);
|
||||
|
||||
private Process _runningProcess;
|
||||
|
||||
public int Start(string executable, string arguments, string workingDir)
|
||||
|
|
@ -43,7 +41,7 @@ namespace Microsoft.DotNet.Watcher.Core.Internal
|
|||
{
|
||||
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.FileSystemGlobbing": "1.0.0-*",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1-*",
|
||||
"System.Diagnostics.Process": "4.1.0-*"
|
||||
"Microsoft.Extensions.ProcessHelper.Sources": {
|
||||
"type": "build",
|
||||
"version": "1.0.0-*"
|
||||
}
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
|
|
|
|||
|
|
@ -4,14 +4,12 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Microsoft.DotNet.Watcher.Core.Internal;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.DotNet.Watcher.FunctionalTests
|
||||
{
|
||||
public class DotNetWatchScenario : IDisposable
|
||||
{
|
||||
private static readonly TimeSpan _processKillTimeout = TimeSpan.FromSeconds(30);
|
||||
|
||||
protected const string DotnetWatch = "dotnet-watch";
|
||||
|
||||
protected static readonly string _repositoryRoot = FindRepoRoot();
|
||||
|
|
@ -38,7 +36,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests
|
|||
{
|
||||
if (!WatcherProcess.HasExited)
|
||||
{
|
||||
WatcherProcess.KillTree(_processKillTimeout);
|
||||
WatcherProcess.KillTree();
|
||||
}
|
||||
WatcherProcess.Dispose();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
"dependencies": {
|
||||
"dotnet-test-xunit": "1.0.0-dev-*",
|
||||
"Microsoft.Extensions.DependencyInjection": "1.0.0-*",
|
||||
"Microsoft.Extensions.ProcessHelper.Sources": {
|
||||
"type": "build",
|
||||
"version": "1.0.0-*"
|
||||
},
|
||||
"Microsoft.DotNet.Watcher.Core": "1.0.0-*",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1-*",
|
||||
"Newtonsoft.Json": "8.0.2",
|
||||
|
|
|
|||
Loading…
Reference in New Issue