0

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...

Tiny Wang
  • 10,423
  • 1
  • 11
  • 29
Medinoc
  • 6,577
  • 20
  • 42

2 Answers2

1

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.

omajid
  • 14,165
  • 4
  • 47
  • 64
0

In my case, I had an ASP.NET application that starts up several sub ASP.NET processes. When I shutdown IIS, I wanted the plugin processes to gracefully shutdown, so I added a /shutdown GET route that calls IHostApplicationLifetime.StopApplication(). Whenever I called it, however, it would block and not actually shut down the application.

The fix was that, in my host application, where I start up the processes, I needed to set UseShellExecute = true. This completely solved my problem as my host application could do a GET request to all the plugin processes and they would shutdown almost immediately.

Strange but it is what it is.

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77