Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -41,11 +42,19 @@ public static void KillTree(this Process process, TimeSpan timeout)

private static void GetAllChildIdsUnix(int parentId, ISet<int> children, TimeSpan timeout)
{
RunProcessAndWaitForExit(
"pgrep",
$"-P {parentId}",
timeout,
out var stdout);
string stdout;
try
{
RunProcessAndWaitForExit(
"pgrep",
$"-P {parentId}",
timeout,
out stdout);
}
catch (Win32Exception)
{
return;
}

if (!string.IsNullOrEmpty(stdout))
{
Expand All @@ -72,11 +81,26 @@ private static void GetAllChildIdsUnix(int parentId, ISet<int> children, TimeSpa

private static void KillProcessUnix(int processId, TimeSpan timeout)
{
RunProcessAndWaitForExit(
"kill",
$"-TERM {processId}",
timeout,
out var stdout);
try
{
using (Process process = Process.GetProcessById(processId))
{
process.Kill();
process.WaitForExit((int)timeout.TotalMilliseconds);
}
}
catch (ArgumentException)
{
// Ignore if process has already exited.
}
catch (InvalidOperationException)
{
// Ignore if process has already exited.
}
catch (Win32Exception)
{
// Ignore permission or process-not-found errors.
}
}

private static void RunProcessAndWaitForExit(string fileName, string arguments, TimeSpan timeout, out string stdout)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetFrameworkCurrent)</TargetFrameworks>
<EnableDefaultItems>true</EnableDefaultItems>
<!-- ActiveIssue in AssemblyInfo.cs -->
<IgnoreForCI>true</IgnoreForCI>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@
using Xunit;

[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]
[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/34090")] // Note: remove IgnoreForCI from .csproj when reenabling
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting.IntegrationTesting;
Expand All @@ -16,6 +16,7 @@ namespace Microsoft.AspNetCore.Hosting.FunctionalTests
{
public class ShutdownTests
{
private const int SIGINT = 2;
private static readonly string StartedMessage = "Started";
private static readonly string CompletionMessage = "Stopping firing\n" +
"Stopping end\n" +
Expand Down Expand Up @@ -50,23 +51,22 @@ private async Task ExecuteShutdownTest(string testName, string shutdownMechanic)
builder.AddXunit(_output);
});

// TODO refactor deployers to not depend on source code
// see https://github.com/dotnet/extensions/issues/1697 and https://github.com/dotnet/aspnetcore/issues/10268
#pragma warning disable 0618
var applicationPath = string.Empty; // disabled for now
#pragma warning restore 0618
string applicationPath = AppContext.BaseDirectory;

Version version = Environment.Version;
var deploymentParameters = new DeploymentParameters(
applicationPath,
RuntimeFlavor.CoreClr,
RuntimeArchitecture.x64)
{
ApplicationName = "Microsoft.Extensions.Hosting.TestApp",
TargetFramework = $"net{version.Major}.{version.Minor}",
ApplicationType = ApplicationType.Portable,
PublishApplicationBeforeDeployment = true,
PreservePublishedApplicationForDebugging = true,
StatusMessagesEnabled = false
};
deploymentParameters.ApplicationPublisher = new ExistingOutputApplicationPublisher(applicationPath);
Comment on lines +62 to +69

deploymentParameters.EnvironmentVariables["DOTNET_STARTMECHANIC"] = shutdownMechanic;

Expand Down Expand Up @@ -132,16 +132,10 @@ private void SendShutdownSignal(Process hostProcess)

private static void SendSIGINT(int processId)
{
var startInfo = new ProcessStartInfo
if (kill(processId, SIGINT) != 0)
{
FileName = "kill",
Arguments = processId.ToString(),
RedirectStandardOutput = true,
UseShellExecute = false
};

var process = Process.Start(startInfo);
WaitForExitOrKill(process);
throw new Win32Exception(Marshal.GetLastPInvokeError());
}
}

private static void WaitForExitOrKill(Process process)
Expand All @@ -154,5 +148,22 @@ private static void WaitForExitOrKill(Process process)

Assert.Equal(0, process.ExitCode);
}

private sealed class ExistingOutputApplicationPublisher : ApplicationPublisher
{
private readonly string _applicationPath;

public ExistingOutputApplicationPublisher(string applicationPath)
: base(applicationPath)
{
_applicationPath = applicationPath;
}

public override Task<PublishedApplication> Publish(DeploymentParameters deploymentParameters, ILogger logger)
=> Task.FromResult(new PublishedApplication(_applicationPath, logger));
}

[DllImport("libc", SetLastError = true)]
private static extern int kill(int pid, int sig);
}
}
Loading