Home > Software design >  Gracefully stop .NET Core server with console or client action
Gracefully stop .NET Core server with console or client action

Time:02-26

I'm in the process of porting some server application from .NET Framework WCF to .NET Core, but I'm having trouble managing the server exit. On our current WCF server, we allow quitting both from a WCF request, and from a console input:

    static void Main()
    {
        hExit = new ManualResetEvent(false);
        StartServer();

        Console.WriteLine("Server started. Press [Enter] to quit.");
        char key;
        while((key=WaitForKeyOrEvent(hExit)) != '\0' && key != '\r') { }
        Console.WriteLine();

        StopServer();
    }

    private static char WaitForKeyOrEvent(System.Threading.WaitHandle hEvent)
    {
        const int Timeout = 500;
        bool dueToEvent = false;
        while(!Console.KeyAvailable)
        {
            if(hEvent.WaitOne(Timeout, false))
            {
                dueToEvent = true;
                break;
            }
        }
        char ret = '\0';
        if(!dueToEvent)
        {
            ret = Console.ReadKey().KeyChar;
            if(ret == '\0')
                ret = char.MaxValue;
        }
        return ret;
    }

    ...

    class ServerObj : IMyWcfInterface
    {
        void IMyWcfInterface.ExitServer() { hExit.Set(); }
    }

Would this approach also work in .NET Core? (using some other tech than WCF of course, since it was abandoned) I vaguely remember hearing that KeyAvailable/ReadKey might not work for an application in a Docker Container, and use of Containers is one of the "end goals" of migrating to .NET Core...

CodePudding user response:

Generally, when running in a container, you generally don't have access to an input device (think keyboard). So that option is not reliable in a containerized application.

Listening to some sort of network request (eg, HTTP, grpc, protobuf) could work, but you would have to be sure that the source of the request is valid and wasn't a malicious entity attacking your application and forcing it to shutdown.

The idiomatic approach in a container environment (eg, Kubernetes, Docker ) is that the container engine sends your application Linux signals such as SIGTERM. docker stop will do this, as will Kubernetes when stopping your pods. Your application should then handle that and shut down correctly.

The implementation is different depending on whether you are using ASP.NET Core or not.

In ASP.NET Core you can use IApplicationLifetime.ApplicationStopping to register some code to be called when the application is being stopped.

Here's a StackOverflow answer that covers the implementation side: graceful shutdown asp.net core

If you are not using ASP.NET Core, you can handle AppDomain.ProcessExit to register a handler to be called when the application is stopping.

  • Related