0

I am trying to handle prestop event of kuberenetes on my application but I didn't receive any events on my .net core console application

lifecycle:
      postStart:
        tcpSocket:
          port: 13000
      preStop:
        tcpSocket:
          port: 13001

I am receiving on event log

FailedPreStopHook pod/podname-795764db56-9q9pg Cannot run handler: invalid handler: &LifecycleHandler{Exec:nil,HTTPGet:nil,TCPSocket:&TCPSocketAction{Port:{0 13001 },Host:,},}

I have tried another solution to start working with native functions like

[DllImport("Kernel32")]
        private static extern bool SetConsoleCtrlHandler(SetConsoleCtrlEventHandler handler, bool add);

But I am able only to run it on windows environment but once I go to linux container I receive error

Unhandled exception. System.DllNotFoundException: Unable to load shared library 'Kernel32' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libKernel32: cannot open shared object file: No such file or directory

Please advice if there is any other solution to this issue to handle closing greacefully for consol application on linux contianer environment.

Victor Faltas
  • 168
  • 1
  • 9

1 Answers1

0

ConsoleCtrlEventHandler is only available under windows. You should use System.Runtime.InteropServices.PosixSignalRegistration in a Linux container and under Windows:

var isCancelRequested = false;
var signal = "none";
using (var protectSIGINTfromGC = PosixSignalRegistration.Create(PosixSignal.SIGINT, (signalContext) =>
{
    signal = "SIGINT";
    signalContext.Cancel = true;
    isCancelRequested = true;
}))
{
    /* Inovke your Root command handler here */
}

You have to protect the event handler from being collected by the garbage collector, see this Answer.

PosixSignalRegistration was introduced with .NET core 6.0.
For older versions, AppDomain.CurrentDomain.ProcessExit is availavle and is raised on SIGTERM and Console.CancelKeyPress is raised on SIGINT.

PosixSignalRegistration can cancel SIGTERM so you can clean up outside the event handler. With ProcessExit you have to can clean up inside the event handler:

static void Main(string[] args)
{
    Console.WriteLine();
    Console.WriteLine($"Process ID = {Environment.ProcessId}");
    var cancel = false;
    Console.CancelKeyPress += new ConsoleCancelEventHandler((s, e) =>
    {
        Console.WriteLine($"CancelKeyPress");
        e.Cancel = true; // not terminate immediately
        cancel = true;
    });
    AppDomain.CurrentDomain.ProcessExit += new EventHandler((s, e) =>
    {
        Console.WriteLine($"ProcessExit");
        Console.WriteLine($"Process {Environment.ProcessId} exited gracefully (SIGTERM).");
    });
    do
    {
        Thread.Sleep(10);
    } while (!cancel);
    Console.WriteLine($"Process {Environment.ProcessId} exited gracefully (SIGINT).");
}

The results:

$ dotnet run &
Process ID = 4113
$ kill -s INT 4113
CancelKeyPress
Process 4113 exited gracefully (SIGINT).
$ dotnet run &
Process ID = 4395
$ kill -s TERM 4395
ProcessExit
Process 4395 exited gracefully (SIGTERM).
Torsten Crull
  • 123
  • 3
  • 9