Aspire fails to trigger IHostApplicationLifetime.ApplicationStopping in hosted projects on Windows (via Dashboard Stop or AppHost Ctrl+C)
Is there an existing issue for this?
- [x] I have searched the existing issues
Describe the bug
On the Windows operating system, when a .NET project (e.g., a Worker Service or ASP.NET Core application) is hosted by Aspire AppHost, the IHostApplicationLifetime.ApplicationStopping event registered within it fails to trigger. This occurs regardless of whether the stop action is initiated via the Aspire Dashboard UI or by pressing Ctrl+C in the terminal running the AppHost to stop the entire application. This prevents the application from executing its graceful shutdown logic (e.g., processing pending tasks in memory or releasing resources), potentially causing data loss or inconsistent states.
Expected Behavior
Whether stopping a single resource via the Aspire Dashboard or stopping the entire application via Ctrl+C in the AppHost terminal, the Aspire AppHost should send the appropriate signal (e.g., SIGINT or an equivalent mechanism) to its managed child processes. This signal should trigger the IHostApplicationLifetime.ApplicationStopping event within the child process, allowing the application to perform graceful shutdown.
Steps To Reproduce
- Create an Aspire Solution: Set up a basic Aspire solution with an AppHost project and a target .NET project (e.g., ASP.NET Core Worker Service or Web API, referred to as
YourServiceProjectbelow). - Implement
ApplicationStoppingHandler in Service Project: InYourServiceProject/Program.cs, injectIHostApplicationLifetimeand register a handler for theApplicationStoppingevent. Include clear logging within the handler:var lifetime = app.Services.GetRequiredService<IHostApplicationLifetime>(); var logger = app.Services.GetRequiredService<ILogger<Program>>(); lifetime.ApplicationStopping.Register(() => { logger.LogInformation(">>>>>>>>>> ApplicationStopping triggered! Timestamp: {Timestamp}", DateTime.UtcNow.ToString("O")); // Optional: Add Thread.Sleep(1000) with logging to verify execution duration }); - (Optional but Recommended) Add File Logging: Configure file logging (e.g., using
NetEscapades.Extensions.Logging.RollingFile) inYourServiceProjectto capture logs reliably, especially during shutdown. - (Optional but Recommended) Add Background Service: Include a simple
BackgroundServicethat depends on thestoppingTokento simulate work and graceful shutdown logic (e.g., processing items from a channel). - Ensure Aspire Environment is Set: Verify that the
DOTNET_ASPIRE_ENVIRONMENTvariable is correctly set for the service process when launched by AppHost (e.g., vialaunchSettings.jsonorWithEnvironment). - Run the AppHost: Execute
dotnet run --project YourAppHost.csprojin a terminal on Windows. - Attempt Stop via Dashboard: Open the Aspire Dashboard, select the
YourServiceProjectresource, and click the "Stop" button. - Observe Logs: Check the logs for
YourServiceProject(console output or file logs). Result: The "ApplicationStopping triggered!" log message is not present. - Restart the AppHost: Run
dotnet run --project YourAppHost.csprojagain. - Attempt Stop via Ctrl+C: In the terminal window running the AppHost, press
Ctrl+C. - Observe Logs: Check the logs for
YourServiceProject. Result: The "ApplicationStopping triggered!" log message is not present. - Verify Standalone Behavior: Run
YourServiceProjectdirectly (dotnet runfrom its directory) and pressCtrl+C. Result: The "ApplicationStopping triggered!" log message is present.
Exceptions (if any)
No exceptions are thrown. The issue is the absence of the expected event trigger.
.NET Version info
`PS D:> dotnet --info .NET SDK: Version: 9.0.300-preview.0.25177.5 Commit: 3d5b396331 Workload version: 9.0.300-manifests.1e5233e8 MSBuild version: 17.14.0-preview-25175-08+5880e1c75
运行时环境: OS Name: Windows OS Version: 10.0.26100 OS Platform: Windows RID: win-x64 Base Path: C:\Program Files\dotnet\sdk\9.0.300-preview.0.25177.5\
已安装 .NET 工作负载: 没有要显示的已安装工作负载。 配置为在安装新清单时使用 loose manifests。
Host: Version: 9.0.3 Architecture: x64 Commit: 831d23e561
.NET SDKs installed: 9.0.200 [C:\Program Files\dotnet\sdk] 9.0.300-preview.0.25177.5 [C:\Program Files\dotnet\sdk]
.NET runtimes installed: Microsoft.AspNetCore.App 6.0.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 8.0.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 9.0.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 9.0.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 6.0.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 8.0.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 9.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 9.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 8.0.14 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 9.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 9.0.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found: x86 [C:\Program Files (x86)\dotnet] registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
Environment variables: Not set
global.json file: Not found
Learn more: https://aka.ms/dotnet/info
Download .NET: https://aka.ms/dotnet/download`
Anything else?
- Aspire Version: 9.2.0+0fcb1e9885266c1700c49c16513a6d97480bb058 (or user's version from AppHost logs)
- Operating System: Windows 10/11
Summary of Test Results:
| Scenario | ApplicationStopping Triggered (per logs)? |
Graceful Shutdown Logs (if applicable)? |
|---|---|---|
| Stop Service via Dashboard | No | No |
Stop App via AppHost Terminal Ctrl+C (with background svcs) |
No | No |
Stop App via AppHost Terminal Ctrl+C (background svcs commented) |
No | (N/A) |
Run Service Standalone + Ctrl+C |
Yes | Yes |
I’m assuming these tests are on windows only
Unfortunately Windows doesn't have an API to allow us to send CTRL-C to a child process in either of these cases.
@dbreshears it does but dcp needs to change how it creates the process (to use a process group)
We just updated the orchestrator to send ctrl+break when closing processes on Windows; I believe that should fix this particular issue.
I've confirmed that I hit ApplicationStopping with the updated orchestrator. I'm going to close this issue out since we seem to be fixed in main, but let us know if you run into any further issues.