How to send SIGTERM (graceful shutdown) to a .NET Core process in MacOS/Linux
Simulate shutdown during development
tldr: if you're already familiar with graceful shutdown, then feel free to scroll down to "How to send termination (SIGTERM) signal"
What is graceful shutdown and why should I care?
Personally I think it's very common to write applications with a state of mind assuming that the application will be running all the time, especially if you're developing a web application or an API which typically is a long-running process. It happens though that our applications crashes and must be restarted, or it happens that we host them in container orchestrators (read Kubernetes) that can decide to kill your application at any give time. In this case, it becomes valuable to think about shutting down you application while causing the least amount of harm possible during this shutdown period. For example, you might want to not start writing to disk if you already know the application is about to shut down. To add this kind of functionality, extra code with the only responsibility to exit your application gracefully, is called graceful shutdown.
It becomes important to simulate a shutdown signal in order to ensure your application terminates in a reasonable way. For me I had to deal with this when starting to host more and more services in Kubernetes, since Kubernetes can (potentially) kill your pod at any given time. I also had problems with the console itself, and could not send Ctrl+C
, which is why I found out about the kill
command.
How to send termination (SIGTERM) signal
- Start your application with:
Console.WriteLine($"Process id: {Process.GetCurrentProcess().Id}")
- Your application should now be running, and you have the process id in your console. Copy this process id.
- Open another terminal, and use the following
kill
command to send a SIGTERM:kill -s TERM <process_id>
TERM here means SIGTERM, which means to - in a polite way - to ask the application to shutdown.
This is equivalent of usingCtrl+C
in the terminal running your application. - Watch your application receive a shutdown signal. .NET Core by default uses a ConsoleLifetime class that is wired up by default and listens to this signal.
What's the difference between SIGTERM and SIGKILL?
Both these are shutdown signals. The latter is more aggressive than the other. As mentioned, SIGTERM means to "in a polite way" ask the application to shutdown. SIGKILL on the other hand is a hard exit, where your application has no time to gracefully shutdown, but is just instantly killed. If you're curious you can read more about the different termination signals here: Termination Signals.
Summary
kill
can be very useful when adding graceful shutdown to your application and want to test it locally.
Useful links:
- Introducing IHostLifetime and untangling the Generic Host startup interactions by Andrew Lock
- Graceful termination in Kubernetes with ASP.NET Core by Mark Vincze (even though the post uses the now deprecated IApplicationLifetime, it's still very valuable)
- IHostApplicationLifetime
- Although not strictly related to SIGTERM or SIGKILL, but more related to "graceful shutdown", I highly recommend this blog post series by Stephen Cleary on cancellation tokens