Windows 上的 .NET Core 应用程序能否捕获 SIGTERM 事件?

Mik*_*sen 5 .net docker .net-core docker-for-windows

我很好奇在 Windows 上运行的用 .NET Core 编写的控制台应用程序是否可以拦截 SIGKILL 事件并且基本上知道它正在被终止。这是我正在尝试的代码:

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine($"Hello from PID {Process.GetCurrentProcess().Id}, press CTRL+C to exit.");

        AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()).Unloading += context =>
        {
            Console.WriteLine("SIGTERM received, exiting program...");
        };

        Console.CancelKeyPress += (s, e) =>
        {
            Console.WriteLine("SIGINT received, exiting program...");
            Environment.Exit(0);
        };

        try
        {
            await Task.Delay(Timeout.Infinite);
        }
        finally
        {
            Console.WriteLine("Finally executed..");
        }

    }
Run Code Online (Sandbox Code Playgroud)

当我从命令行运行程序时,我可以使用 CTRL+C 组合键终止它。这将激活CancelKeyPress以及Unloading。如果我以其他方式终止程序(使用 Windows 任务管理器的“结束进程”功能或Stop-ProcessPowerShell 命令),该进程将简单地结束,而不会向控制台写入任何输出。

这是一个更大目标的一部分,即捕获 Docker 容器关闭。在 Windows 上,该docker stop命令将使用 SIGTERM 终止主进程。此行为可在 Linux Docker 上使用--stop-signalSTOPSIGNAL功能进行配置,但这些功能尚未在 Windows 上实现。

Ste*_*ary 9

在 Windows 上,docker stop 命令将使用 SIGTERM 终止主进程。

从版本开始1709(对于主机和基本映像),使用基本映像microsoft/windowsservercoremicrosoft/nanoserverCTRL_CLOSE_EVENT仅发送到主进程的Windows 容器。

从版本开始1803,使用这些基本映像的 Windows 容器将发送CTRL_SHUTDOWN_EVENT到容器中运行的所有进程。

因此,根据您的版本,Docker 可能会发送CTRL_CLOSE_EVENTCTRL_SHUTDOWN_EVENT.

它们与 Ctrl-C 信号不同,后者是CTRL_C_EVENT. .NET 的Console.CancelKeyPress唯一句柄CTRL_C_EVENT(或密切相关的CTRL_BREAK_EVENT,因此不会调用CTRL_CLOSE_EVENTCTRL_SHUTDOWN_EVENT

如果我以其他方式终止程序(使用 Windows 任务管理器的“结束进程”功能或 Stop-Process PowerShell 命令),该进程将简单地结束,而不会向控制台写入任何输出。

不可能处理所有终止信号。我相信任务管理器这些天试图做一个“温和”的关闭,在这种情况下可能是发送CTRL_CLOSE_EVENT,但也完全有可能只是TerminateProcess一个进程,它在没有任何信号或任何东西的情况下立即杀死它。

但是识别 Docker 启动的关闭并对其做出响应是可能的,因为它首先发送一个好的信号并且仅在超时后终止。

.NET 运行时将识别CTRL_CLOSE_EVENT为进程退出请求,但由于 Windows 的 Docker 的较新版本已切换到CTRL_SHUTDOWN_EVENT,我相信.NET 将不再对 Windows 容器进行正常关闭

我知道的唯一解决方法是安装您自己的控制台控制事件处理程序。我建议处理CTRL_C_EVENTCTRL_CLOSE_EVENTCTRL_SHUTDOWN_EVENT所有的只是一个普通的“关机”信号