I've been trying different approaches to gracefully shutdown my application by reacting to the SIGTERM signal, however I can't seem to make it work.
I've implemented the following service:
public class ShutdownService : IHostedService
{
private readonly IHostApplicationLifetime _appLifetime;
private readonly ILogger<ShutdownService> _logger;
public ShutdownService(IHostApplicationLifetime appLifetime, ILogger<ShutdownService> logger)
{
_appLifetime = appLifetime;
_logger = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Initializing shutdown service.");
Console.CancelKeyPress += (sender, eventArgs) =>
{
_logger.LogInformation("Ctrl-C detected. Initiating shutdown...");
_appLifetime.StopApplication();
eventArgs.Cancel = true;
};
_logger.LogInformation("Now listening to Ctrl-C.");
cancellationToken.Register(() =>
{
_logger.LogInformation("SIGTERM detected. Initiating shutdown...");
_appLifetime.StopApplication();
});
AppDomain.CurrentDomain.ProcessExit += (sender, e) =>
{
_logger.LogInformation("SIGTERM detected. Initiating shutdown...");
_appLifetime.StopApplication();
};
_logger.LogInformation("Now listening to SIGTERM.");
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Executing graceful shutdown.");
return Task.CompletedTask;
}
}
I've registered it in my services:
Host.CreateDefaultBuilder(args)
.UseDefaultServiceProvider(o => o.ValidateScopes = false)
.UseSystemd()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<ShutdownService>();
}
In my dockerfile, I'm using a shell script as entrypoint since I have to start multiple applications when the container starts. The script looks like this:
#!/bin/bash
dotnet /App/myGracefulShutdownApp.dll &
pid=$!
dotnet /App2/myOtherApp.dll &
trap 'kill -SIGTERM $pid' SIGTERM SIGINT
wait $pid
I've verified, that the ShutdownService is running, when the container is started. I've verified, that the correct process id gets killed with the trap command when I stop the container.
The container is run as a non-root user, if that matters. I've also tried using the kill command from within the container (to see if the user has the permissions to execute the kill command and it does), but the application still does not execute StopAsync.
I'm happy to provide more information if needed. Thank you for your help already!