Killing gracefully a .NET Core daemon running on Linux

26,070

Solution 1

You want to be able to send a SIGTERM to the running process:

kill <PID>

And the process should handle it to shutdown correctly.

Unfortunately .NET Core is not well documented, but it is capable of handling Unix signals (in a different fashion from Mono). GitHub issue

If you use Ubuntu with Upstart, what you need is to have an init script that sends the the kill signal on a stop request: Example init script

Add a dependency to your project.json:

"System.Runtime.Loader": "4.0.0"

This will give you the AssemblyLoadContext.

Then you can handle the SIGTERM event:

AssemblyLoadContext.Default.Unloading += MethodInvokedOnSigTerm;

Note:

Using Mono, the correct way of handling it would be through the UnixSignal: Mono.Unix.Native.Signum.SIGTERM

EDIT:

As @Marc pointed out in his recent answer, this is not anymore the best way to achieve this. From .NET Core 2.0 AppDomain.CurrentDomain.ProcessExit is the supported event.

Solution 2

.NET Core has considerably evolved since @Stefano's answer a year ago. In .NET Core 2.0, you can now use the well-known AppDomain.CurrentDomain.ProcessExit event instead of AssemblyLoadContext.Default.Unloading. It works fine for console applications on Linux, also in Docker.

Share:
26,070

Related videos on Youtube

user4388177
Author by

user4388177

Updated on July 09, 2022

Comments

  • user4388177
    user4388177 almost 2 years

    I created a .NET Core console application running as a daemon on a Ubuntu 14.04 machine.

    I want to stop the service without forcing it, being able to handle a kill event.

    How can I achieve this?

    • lasseschou
      lasseschou over 7 years
      Care to share your code - turning a .NET Core console app into an Ubuntu daemon?
    • user4388177
      user4388177 over 7 years
      The only thing I did was copying a default init script from GitHub; the start function calls dotnet library.dll and the stop one: kill dotnet library.dll.
  • dcinadr
    dcinadr almost 8 years
    This works if the application is stops on its own gracefully. But if the kill command is called it does not trigger "AssemblyLoadContext.Default.Unloading". Am I doing something wrong?
  • Stefano d'Antonio
    Stefano d'Antonio almost 8 years
    What version of .NET Core are you using? Are you modifying the load context at some point?
  • dcinadr
    dcinadr almost 8 years
    Version: 1.0.0-preview2-003121 ... I have also noticed that when I run "dotnet run" it starts 2 processes. I think this is the reason it is not working because it kills one of the processes but not both.
  • Stefano d'Antonio
    Stefano d'Antonio almost 8 years
    Try getting to the published DLL folder and run using: dotnet <DllName>.dll (without run) that should run just one process and you can try killing that one.
  • dcinadr
    dcinadr over 7 years
    Thank you. Yes, that is similar to how I got it working. Only difference I had was "dotnet exec <DllName>.dll".
  • Stefano d'Antonio
    Stefano d'Antonio over 7 years
    I didn't know about exec so I searched quickly and I found this: github.com/dotnet/cli/issues/2243 but I'm assuming has a similar behaviour to dotnet <dll>.
  • Stefano d'Antonio
    Stefano d'Antonio over 7 years
    @dcinadr Here it recommends to use it without exec, but I would be curious to know the difference if you know. github.com/dotnet/core/issues/77
  • RQDQ
    RQDQ over 5 years
    I made a simple example of how to handle this event: github.com/rquackenbush/DotNetSigTermTest
  • Parag
    Parag over 5 years
    AppDomain.CurrentDomain.ProcessExit only allows for 2 seconds of cleanup, and there is no way to override it using managed code.
  • Anders Emil
    Anders Emil almost 5 years
    @Parag I think you misread the documentation, or it has been changed. This time limit is only in .NET Framework, not in .NET Core. docs.microsoft.com/en-us/dotnet/api/…
  • Parag
    Parag almost 5 years
    @AndersEmil I am sure it applies for .net core. Check the "Applies to" section in the docs link you sent.
  • Anders Emil
    Anders Emil almost 5 years
    @Parag the article is about the ProcessExit event, not the time limit. In the purple Note box it clearly says that the time limit does not exist in .NET Core, I'm surprised you miss it.
  • Parag
    Parag about 4 years
    @AndersEmil I re-read it and you are right. Sorry for the misinformation.