我很好奇,如果在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..");
}
}
当我从命令行运行程序时,可以使用CTRL + C组合键终止它。这将触发CancelKeyPress
和Unloading
。如果我以其他方式终止程序(使用Windows任务管理器的“结束进程”功能,或Stop-Process
PowerShell命令),则该进程仅会结束,而不会将任何输出写入控制台。
这是一个更大目标的一部分,该目标是捕获Docker容器关闭。在Windows上,docker stop
命令将使用SIGTERM终止主进程。可使用--stop-signal
或STOPSIGNAL
功能在Linux Docker上配置此行为,但是Windows尚未实现这些功能。
在Windows上,docker stop命令将使用SIGTERM终止主进程。
1709
因此,根据您的版本,Docker可能会发送microsoft/windowsservercore
或microsoft/nanoserver
。
这些与Ctrl-C信号CTRL_CLOSE_EVENT
不同。 As of version 1803
, Windows containers using those base images will send CTRL_SHUTDOWN_EVENT
to all processes running in the container.,因此不会为1803
或CTRL_SHUTDOWN_EVENT
调用。
如果我以其他方式终止程序(使用Windows任务管理器的“结束进程”功能或Stop-Process PowerShell命令),则该进程将简单结束,而不会将任何输出写入控制台。
不可能处理所有的杀死信号。我相信这些天的任务管理器会尝试执行“温和的”关闭,在这种情况下,该关闭可能正在发送CTRL_CLOSE_EVENT
,但也完全可能只是CTRL_SHUTDOWN_EVENT
一个进程,该进程将立即杀死它而没有任何信号或任何东西。 >
但是可以识别由Docker启动的关闭并做出响应,因为它首先发送一个不错的信号,并且仅在超时后才终止。
CTRL_C_EVENT
,但是由于适用于Windows的较新版本的Docker已切换为.NET's Console.CancelKeyPress
only handles CTRL_C_EVENT
(or the closely-related CTRL_BREAK_EVENT
),因此我相信Console.CancelKeyPress
。
我知道的唯一解决方法是安装自己的控制台控件事件处理程序。我推荐CTRL_C_EVENT
。