I need to notify systemd
that my service has started up successfully, and a task it needs to run after startup requires that the server is already listening
This is what I did to overcome the issue.
1- I registered ApplicationStopped
event. So that it brute force terminates the app by calling Kill()
method of the current process.
public void Configure(IHostApplicationLifetime appLifetime) {
appLifetime.ApplicationStarted.Register(() => {
Console.WriteLine("Press Ctrl+C to shut down.");
});
appLifetime.ApplicationStopped.Register(() => {
Console.WriteLine("Terminating application...");
System.Diagnostics.Process.GetCurrentProcess().Kill();
});
}
See IHostApplicationLifetime docs
2- Don't forget to use the UseConsoleLifetime()
while building the host.
Host.CreateDefaultBuilder(args).UseConsoleLifetime(opts => opts.SuppressStatusMessages = true);
See useconsolelifetime docs
On .Net Core 1.x
it is safe to just run IWebHost.Start()
and assume that the server is initialized afterwards (instead of Run()
that blocks the thread). Check the source.
var host = new WebHostBuilder()
.UseKestrel()
(...)
.Build();
host.Start();
If you are using .NET Core 2.0 Preview 1
(or later), the source is different, the synchronous method is not available anymore so you should await IWebHost.StartAsync()
and assume everything is ready afterwards.
You may use Microsoft.AspNetCore.Hosting.IApplicationLifetime:
/// <summary>
/// Triggered when the application host has fully started and is about to wait
/// for a graceful shutdown.
/// </summary>
CancellationToken ApplicationStarted { get; }
Look into this SO post for the configuration example.
This is what I ended up going with, for now. Seems to be working fine:
host.Start();
Log.Information("Press Ctrl+C to shut down...");
Console.CancelKeyPress += OnConsoleCancelKeyPress;
var waitHandles = new WaitHandle[] {
CancelTokenSource.Token.WaitHandle
};
WaitHandle.WaitAll(waitHandles);
Log.Information("Shutting down...");
Then, in the Ctrl+C event handler:
private static void OnConsoleCancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
Log.Debug("Got Ctrl+C from console.");
CancelTokenSource.Cancel();
}