dotnet / dotnet/aspnetcore

IHostedService StopAsync and OnStopping/OnStopped events not called with IIS preload enabled

Open
#28,089 19 comments 0 reactions 0 assignees View on GitHub
:heavy_check_mark: Resolution: Fixed affected-very-few area-networking bug investigate Needs: Attention :wave: severity-minor
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 5h
Merged PRs (30d)
276

Description

In summary, if I

- Install the "Application Initialization module" in IIS
- Set "StartMode: AlwaysRunning" for the app pool
- Set "Preload Enabled: True" for the website

The IHostedService StopAsync method and OnStopping/OnStopped events are not called when either recycling the app pool or restarting IIS (iisreset). Just disabling "Preload Enabled" fixes the issue.

Not sure this is an IIS or .Net Core issue.

Here is the output of dotnet --info

Host (useful for support):
Version: 3.1.9
Commit: 774fc3d6a9

.NET Core SDKs installed:
No SDKs were found.

.NET Core runtimes installed:
Microsoft.AspNetCore.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

IIS on Windows Server 2019 1809, but same issue on Windows 10 1909.

Code sample:

public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup();
})
.ConfigureServices(services =>
{
services.AddHostedService();
});
}

internal class LifetimeEventsHostedService : IHostedService
{
private readonly ILogger _logger;
private readonly IHostApplicationLifetime _appLifetime;

public LifetimeEventsHostedService(
ILogger logger,
IHostApplicationLifetime appLifetime)
{
_logger = logger;
_appLifetime = appLifetime;
}

public Task StartAsync(CancellationToken cancellationToken)
{
_appLifetime.ApplicationStarted.Register(OnStarted);
_appLifetime.ApplicationStopping.Register(OnStopping);
_appLifetime.ApplicationStopped.Register(OnStopped);

return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("StopAsync has been called.");

return Task.CompletedTask;
}

private void OnStarted()
{
_logger.LogInformation("OnStarted has been called.");
}

private void OnStopping()
{
_logger.LogInformation("OnStopping has been called.");
}

private void OnStopped()
{
_logger.LogInformation("OnStopped has been called.");
}
}

StartAsync and OnStarted are always called. It seems the process is killed by IIS instead of cleanly shutting down when preload is enabled.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.