Skip to content

Fix shutdown hang with IIS#65733

Open
BrennanConroy wants to merge 5 commits intomainfrom
brecon/iislifetime
Open

Fix shutdown hang with IIS#65733
BrennanConroy wants to merge 5 commits intomainfrom
brecon/iislifetime

Conversation

@BrennanConroy
Copy link
Member

@BrennanConroy BrennanConroy commented Mar 10, 2026

Fixes #65436

dotnet/runtime#116652 revealed what is probably a latent bug in IIS/WAS/Windows where if Preload Enabled = true for your IIS application then machine shutdown can hang forever due to the default 30 second delay blocking the w3wp process from being closed which allows a new w3wp process time to start up, rinse and repeat.

This PR is using a custom IHostLifetime that effectively reverts ConsoleLifetime to the pre-10.0 behavior of not blocking for 30 seconds to workaround whatever bug exists in the lower layers. I have pinged an IIS dev about this, and will push on a solution from that end outside of this change.

@BrennanConroy BrennanConroy marked this pull request as ready for review March 11, 2026 23:34
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a shutdown hang when IIS has Preload Enabled = true by introducing a custom IISHostLifetime that avoids the 30-second blocking sleep added in .NET 10.0's ConsoleLifetime. Also fixes a null reference bug in IISDeployer.

Changes:

  • Adds IISHostLifetime as a replacement for ConsoleLifetime in the IIS in-process hosting path
  • Fixes null dereference in IISDeployer.WaitUntilSiteStarted by moving site.Name access after the null check
  • Adds tests verifying the correct IHostLifetime is used for in-process and out-of-process hosting

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
WebHostBuilderIISExtensions.cs Registers IISHostLifetime and defines the class
IISDeployer.cs Moves site.Name access after null check
StartupTests.cs Adds tests for host lifetime verification
InProcessWebSite/Program.cs Adds HostBuilder test case
InProcessWebSite/Startup.cs Adds GetHostLifetime endpoint

Comment on lines +1467 to +1484
[ConditionalFact]
public async Task OutOfProcessHostlifetime()
{
if (DeployerSelector.IsNewShimTest)
{
// NewShim tests use 2.2 IIS packages which don't have the host lifetime
return;
}

var deploymentParameters = Fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess);
deploymentParameters.TransformArguments((a, _) => $"{a} HostBuilder");

if (deploymentParameters.ServerType == ServerType.IISExpress)
{
return;
}

Assert.Equal("ConsoleLifetime", await GetStringAsync(deploymentParameters, "GetHostLifetime"));
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The early return for IISExpress silently skips the test without any indication. Consider using Skip or a ConditionalFact attribute so test results clearly show the test was skipped rather than appearing to pass.

Copilot uses AI. Check for mistakes.
}

[ConditionalFact]
public async Task InProcessHostlifetime()
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor inconsistency: Hostlifetime should be HostLifetime (capital 'L') to match .NET naming conventions.

Copilot uses AI. Check for mistakes.
// for SIGTERM on Windows we must block this thread until the application is finished
// otherwise the process will be killed immediately on return from this handler

// don't allow Dispose to unregister handlers, since Windows has a lock that prevents the unregistration while this handler is running
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this code is changing in dotnet/runtime#124893


public Task WaitForStartAsync(CancellationToken cancellationToken)
{
_sigTermRegistration = PosixSignalRegistration.Create(PosixSignal.SIGTERM,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that it is SIGINT and SIGQUIT handlers are intentionally missing here since they are not needed by IIS.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, ctrl-c or ctrl-break doesn't make sense for IIS apps.

@jkotas jkotas requested a review from mrek-msft March 12, 2026 17:42
// Does not copy Thread.Sleep(HostOptions.ShutdownTimeout)
// from ConsoleLifetime because that causes machine shutdown to hang
// if Preload Enabled = true
// Likely an IIS/WAS issue.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine as a minimal low-risk fix that can be backported.

For the right fix, I would expect that there is a IIS-native way to subscribe to shutdown and we should not need PosixSignal.SIGTERM handler at all.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I hope we can find a better solution in the future and this is just a temporary solution for customers that are broken by the current behavior.

@BrennanConroy
Copy link
Member Author

/backport to release/10.0

@github-actions
Copy link
Contributor

Started backporting to release/10.0 (link to workflow run)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions feature-iis Includes: IIS, ANCM

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NET10 + IIS (InProcess with Preload Enabled) causes Windows to hang during shutdown

5 participants