Make startup timeout recycle worker process (#25321)

This commit is contained in:
Justin Kotalik 2020-09-01 15:30:28 -07:00 committed by GitHub
parent f0a5233b2c
commit ee712265d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 5 deletions

View File

@ -30,6 +30,7 @@
#define CS_ENABLED L"enabled"
#define CS_ASPNETCORE_HANDLER_CALL_STARTUP_HOOK L"callStartupHook"
#define CS_ASPNETCORE_HANDLER_STACK_SIZE L"stackSize"
#define CS_ASPNETCORE_SUPPRESS_RECYCLE_ON_STARTUP_TIMEOUT L"suppressRecycleOnStartupTimeout"
#define CS_ASPNETCORE_DETAILEDERRORS L"ASPNETCORE_DETAILEDERRORS"
#define CS_ASPNETCORE_ENVIRONMENT L"ASPNETCORE_ENVIRONMENT"
#define CS_DOTNET_ENVIRONMENT L"DOTNET_ENVIRONMENT"

View File

@ -66,6 +66,7 @@ InProcessOptions::InProcessOptions(const ConfigurationSource &configurationSourc
m_fSetCurrentDirectory = equals_ignore_case(find_element(handlerSettings, CS_ASPNETCORE_HANDLER_SET_CURRENT_DIRECTORY).value_or(L"true"), L"true");
m_fCallStartupHook = equals_ignore_case(find_element(handlerSettings, CS_ASPNETCORE_HANDLER_CALL_STARTUP_HOOK).value_or(L"true"), L"true");
m_strStackSize = find_element(handlerSettings, CS_ASPNETCORE_HANDLER_STACK_SIZE).value_or(L"1048576");
m_fSuppressRecycleOnStartupTimeout = equals_ignore_case(find_element(handlerSettings, CS_ASPNETCORE_SUPPRESS_RECYCLE_ON_STARTUP_TIMEOUT).value_or(L"false"), L"true");
m_dwStartupTimeLimitInMS = aspNetCoreSection->GetRequiredLong(CS_ASPNETCORE_PROCESS_STARTUP_TIME_LIMIT) * 1000;
m_dwShutdownTimeLimitInMS = aspNetCoreSection->GetRequiredLong(CS_ASPNETCORE_PROCESS_SHUTDOWN_TIME_LIMIT) * 1000;

View File

@ -118,6 +118,12 @@ public:
return m_strStackSize;
}
bool
QuerySuppressRecycleOnStartupTimeout() const
{
return m_fSuppressRecycleOnStartupTimeout;
}
InProcessOptions(const ConfigurationSource &configurationSource, IHttpSite* pSite);
static
@ -139,6 +145,7 @@ private:
bool m_fWindowsAuthEnabled;
bool m_fBasicAuthEnabled;
bool m_fAnonymousAuthEnabled;
bool m_fSuppressRecycleOnStartupTimeout;
DWORD m_dwStartupTimeLimitInMS;
DWORD m_dwShutdownTimeLimitInMS;
DWORD m_dwMaxRequestBodySize;

View File

@ -169,7 +169,14 @@ IN_PROCESS_APPLICATION::LoadManagedApplication(ErrorContext& errorContext)
errorContext.errorReason = format("ASP.NET Core app failed to start after %d milliseconds", m_pConfig->QueryStartupTimeLimitInMS());
m_waitForShutdown = false;
StopClr();
if (m_pConfig->QuerySuppressRecycleOnStartupTimeout())
{
StopClr();
}
else
{
Stop(/* fServerInitiated */false);
}
throw InvalidOperationException(format(L"Managed server didn't initialize after %u ms.", m_pConfig->QueryStartupTimeLimitInMS()));
}

View File

@ -453,9 +453,10 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess
}
[ConditionalFact]
[RequiresNewHandler]
public async Task StartupTimeoutIsApplied()
{
// From what I can tell, this failure is due to ungraceful shutdown.
// From what we can tell, this failure is due to ungraceful shutdown.
// The error could be the same as https://github.com/dotnet/core-setup/issues/4646
// But can't be certain without another repro.
using (AppVerifier.Disable(DeployerSelector.ServerType, 0x300))
@ -470,11 +471,45 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess
var response = await deploymentResult.HttpClient.GetAsync("/");
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
// Startup timeout now recycles process.
deploymentResult.AssertWorkerProcessStop();
EventLogHelpers.VerifyEventLogEvent(deploymentResult,
EventLogHelpers.InProcessFailedToStart(deploymentResult, "Managed server didn't initialize after 1000 ms."),
Logger);
if (DeployerSelector.HasNewHandler)
{
var responseContent = await response.Content.ReadAsStringAsync();
Assert.Contains("500.37", responseContent);
}
}
}
[ConditionalFact]
[MaximumOSVersion(OperatingSystems.Windows, WindowsVersions.Win10_20H1, SkipReason = "Shutdown hangs https://github.com/dotnet/aspnetcore/issues/25107")]
public async Task StartupTimeoutIsApplied_DisableRecycleOnStartupTimeout()
{
// From what we can tell, this failure is due to ungraceful shutdown.
// The error could be the same as https://github.com/dotnet/core-setup/issues/4646
// But can't be certain without another repro.
using (AppVerifier.Disable(DeployerSelector.ServerType, 0x300))
{
var deploymentParameters = Fixture.GetBaseDeploymentParameters(Fixture.InProcessTestSite);
deploymentParameters.TransformArguments((a, _) => $"{a} Hang");
deploymentParameters.WebConfigActionList.Add(
WebConfigHelpers.AddOrModifyAspNetCoreSection("startupTimeLimit", "1"));
deploymentParameters.HandlerSettings["suppressRecycleOnStartupTimeout"] = "true";
var deploymentResult = await DeployAsync(deploymentParameters);
var response = await deploymentResult.HttpClient.GetAsync("/");
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
StopServer(gracefulShutdown: false);
EventLogHelpers.VerifyEventLogEvents(deploymentResult,
EventLogHelpers.InProcessFailedToStart(deploymentResult, "Managed server didn't initialize after 1000 ms.")
);
EventLogHelpers.VerifyEventLogEvent(deploymentResult,
EventLogHelpers.InProcessFailedToStart(deploymentResult, "Managed server didn't initialize after 1000 ms."),
Logger);
if (DeployerSelector.HasNewHandler)
{