Add support for suspending ANCM startup (#7252)

Uses the `ASPNETCORE_STARTUP_SUSPEND_EVENT` environment variable to get an event name.

Fixes: https://github.com/aspnet/AspNetCore/issues/6972
This commit is contained in:
Pavel Krymets 2019-02-05 15:41:45 -08:00 committed by GitHub
parent ad0377e88f
commit 6a46f48eb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 0 deletions

View File

@ -133,6 +133,30 @@ APPLICATION_INFO::CreateApplication(IHttpContext& pHttpContext)
HRESULT
APPLICATION_INFO::TryCreateApplication(IHttpContext& pHttpContext, const ShimOptions& options)
{
const auto startupEvent = Environment::GetEnvironmentVariableValue(L"ASPNETCORE_STARTUP_SUSPEND_EVENT");
if (startupEvent.has_value())
{
LOG_INFOF(L"Startup suspend event %ls", startupEvent.value().c_str());
HandleWrapper<NullHandleTraits> eventHandle = OpenEvent(SYNCHRONIZE, false, startupEvent.value().c_str());
if (eventHandle == nullptr)
{
LOG_INFOF(L"Unable to open startup suspend event");
}
else
{
auto const suspendedEventName = startupEvent.value() + L"_suspended";
HandleWrapper<NullHandleTraits> suspendedEventHandle = OpenEvent(EVENT_MODIFY_STATE, false, suspendedEventName.c_str());
if (suspendedEventHandle != nullptr)
{
LOG_LAST_ERROR_IF(!SetEvent(suspendedEventHandle));
}
LOG_LAST_ERROR_IF(WaitForSingleObject(eventHandle, INFINITE) != WAIT_OBJECT_0);
}
}
RETURN_IF_FAILED(m_handlerResolver.GetApplicationFactory(*pHttpContext.GetApplication(), m_pApplicationFactory, options));
LOG_INFO(L"Creating handler application");

View File

@ -7,6 +7,7 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
@ -520,6 +521,41 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
Assert.Equal(deploymentResult.ContentRoot + "\\", await deploymentResult.HttpClient.GetStringAsync("/ASPNETCORE_IIS_PHYSICAL_PATH"));
}
[ConditionalFact]
[RequiresNewShim]
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
public async Task StartupIsSuspendedWhenEventIsUsed()
{
var deploymentParameters = _fixture.GetBaseDeploymentParameters();
deploymentParameters.ApplicationType = ApplicationType.Standalone;
deploymentParameters.EnvironmentVariables["ASPNETCORE_STARTUP_SUSPEND_EVENT"] = "ANCM_TestEvent";
var eventPrefix = deploymentParameters.ServerType == ServerType.IISExpress ? "" : "Global\\";
var startWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, eventPrefix + "ANCM_TestEvent");
var suspendedWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, eventPrefix + "ANCM_TestEvent_suspended");
var deploymentResult = await DeployAsync(deploymentParameters);
var request = deploymentResult.AssertStarts();
Assert.True(suspendedWaitHandle.WaitOne(TimeoutExtensions.DefaultTimeoutValue));
// didn't figure out a better way to check that ANCM is waiting to start
var applicationDll = Path.Combine(deploymentResult.ContentRoot, "InProcessWebSite.dll");
var handlerDll = Path.Combine(deploymentResult.ContentRoot, "aspnetcorev2_inprocess.dll");
// Make sure application dll is not locked
File.WriteAllBytes(applicationDll, File.ReadAllBytes(applicationDll));
// Make sure handler dll is not locked
File.WriteAllBytes(handlerDll, File.ReadAllBytes(handlerDll));
// Make sure request is not completed
Assert.False(request.IsCompleted);
startWaitHandle.Set();
await request;
}
private static void MoveApplication(
IISDeploymentParameters parameters,
string subdirectory)