-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Different Exit code when IHost stops from failing (async)IHostedService #67146
Comments
Tagging subscribers to this area: @dotnet/area-extensions-hosting Issue DetailsGiven the following
And
I get an 'error' exit code, which is usefull to detect errors in let's say kubernetes
However when uncommenting the 'await Task...' There is no longer an 'error' exit code
Is there a way to detect this case using the hostbuilder ?
|
The difference in behavior here is that when you don't After the I think it would make sense to set the exit code to something non-zero in this case to indicate that the app has been stopped. Potentially, we may need an option to control the behavior if someone wants to opt-out of it. Thoughts, @davidfowl @Tratcher @maryamariyan ? |
+1. Keeping as-is. Might be good to look for more feedback here before deciding on how to approach this. |
@maryamariyan In my private kubernetes development cluster I already had also the problem that error handling is hard to show without error code. Kubernetes dashboard for ex. would otherwise display the status "finished" or something like that instead of "Failed". But there are many usecases (for ex. Docker) |
Why not change application code to return a non-zero exit code? This feels more like a template change than a change to these APIs tbh. |
How does the app know to return a non-zero exit code? IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.Build();
await host.RunAsync();
Lines 48 to 60 in 8aac5ee
We would somehow need to bubble the exception up through |
Then I would change the title of this issue to make sure that RunAsync throws if we're shutting down the host. We can store the exception and make StopAsync throw observe the exception. |
I think the title is fine - it describes the intended behavior, not the solution. There are other possible solutions here. One would be to store the caught exceptions on the |
What do you think about simply setting |
We shouldn't be setting the exit code. We used to do that a long time ago in the library because of other issues but the application owns the entrypoint.
Maybe it's both? RunAsync is one observer of the Exception that was captured, which rethrows. |
Exiting due to failure with a success exit code is bad.
This seems like the proper thing to do. We can't capture the exception for the generic |
@tmds |
I agree with the ability to have a different exit code. I'd like my Windows service's recovery to get done (restart), but with |
I think an other BackgroundServiceExceptionBehavior value on the enum which sets an exit code on an unhandled error would be good. For Kubernetes when you use a dotnet worker as a cronjob the job is shown as completed with no failure although the background service might have failed. |
Extension I put together just now for a template we're working on that ensures the app exits with a non-zero exit code if a public static class HostExtensions
{
public static async Task RunAndObserveBackgroundServices(this IHost host)
{
var backgroundServiceTasks = host.Services.GetServices<IHostedService>()
.OfType<BackgroundService>().Select(s => s.ExecuteTask);
await host.RunAsync();
if (backgroundServiceTasks.Any(t => t?.IsFaulted == true))
{
// If a BackgroundService failed, set the exit code to -1.
Environment.ExitCode = -1;
}
}
} Simply call this method instead of Alternative is add an additional class BackgroundServiceObserver(IServiceProvider serviceProvider) : IHostedService
{
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task StopAsync(CancellationToken cancellationToken)
{
var backgroundServiceTasks = serviceProvider.GetServices<IHostedService>()
.OfType<BackgroundService>().Select(s => s.ExecuteTask);
if (backgroundServiceTasks.Any(t => t?.IsFaulted == true))
{
// If a BackgroundService failed, set the exit code to -1.
Environment.ExitCode = -1;
}
return Task.CompletedTask;
}
} Given the impact of the current behavior in environments like Kubernetes, Azure Container Apps, Aspire, etc., I think we should prioritize improving this behavior in the runtime. As @msschl suggest, we should add a new value to |
Given the following
Program.cs
And
Worker.cs
I get an 'error' exit code, which is usefull to detect errors in let's say kubernetes
However when uncommenting the 'await Task...'
There is no longer an 'error' exit code
Is there a way to detect this case using the hostbuilder ?
The text was updated successfully, but these errors were encountered: