【发布时间】:2013-09-17 10:18:33
【问题描述】:
本题基于以下问题:Handle CTRL+C on Win32
我正在开发一个多线程服务器,在 Linux 和 Windows 上运行。我不能使用 boost 或其他框架,只能使用 std c++。
我在 win32 端的清理代码有问题。 linux端工作正常:当我想关闭服务器时,我发送SIGINT(带有CTRL+C),信号处理程序设置一个全局变量,主pthread执行清理指令(加入其他pthread,释放堆内存等)。
在 Windows 上,获得相同的行为看起来并不那么简单。 我编写了一个简单的测试程序来了解信号处理程序在 windows 中的工作原理。
#include <iostream>
#include <windows.h>
bool running;
BOOL WINAPI consoleHandler(DWORD signal) {
if (signal == CTRL_C_EVENT) {
running = false;
std::cout << "[CTRL+C]\n";
return TRUE;
}
return FALSE;
}
int main(int argc, char **argv) {
running = true;
if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) {
std::cerr << "Error: " << GetLastError() << '\n';
return -1;
}
std::cout << "Main thread working hard...\n";
while (running) { ; }
for (int i = 0; i < 20; i++)
std::cout << "This is the " << i << "th fake cleanup instruction\n";
return 0;
}
输出如下:
$ test.exe
Main thread working hard...
[CTRL+C]
This is the 0th fake cleanup instruction
This is the 1th fake cleanup instruction
所以主线程很快就被杀死了,只在两条指令之后。在上一个问题中one of the suggestion 是在处理程序中移动清理代码,但并没有真正帮助:
假设处理函数如下所示:
BOOL WINAPI consoleHandler(DWORD signal) {
if (signal == CTRL_C_EVENT) {
running = false;
std::cout << "[CTRL+C]\n";
for (int i = 0; i < 20; i++)
std::cout << "This is the " << i << "th fake cleanup instruction\n";
return TRUE;
}
return FALSE;
}
现在行为更糟了!输出是:
$ test.exe
Main thread working hard...
[CTRL+C]
This is the
根据MSDN看来,进程总是被杀死:
一个 HandlerRoutine 可以执行任何必要的清理,然后取其中之一 以下操作:
- 调用ExitProcess 函数终止进程。
- 返回 FALSE。如果所有注册的处理程序函数都没有返回 TRUE,则默认处理程序终止进程。
- 返回真。在这种情况下,不会调用其他处理函数并且系统终止
过程。
我是否遗漏了一些明显的东西? 终止 win32 控制台进程并执行其清理代码的正确方法是什么?
【问题讨论】:
-
你确定你看到的问题与
cout没有刷新有关吗,基于你从清理中返回true的事实,所以代码终止而不调用您通常在exit中看到的刷新? -
刚刚把
'\n'换成std::endl,输出是一样的。 -
那我恐怕没有进一步的建议了。
-
恐怕你有点误导。关于即将关闭的处理程序 proc 返回值的文档是 not 用于 ctrl-c 处理的。它适用于
CTRL_CLOSE_EVENT、CTRL_LOGOFF_EVENT和CTRL_SHUTDOWN_EVENT。常规的 ctrl-C 处理程序在处理 ctrl-c、接收通知和设置适当的正常关闭方面应该没有问题。如果有机会,我会尝试为您制作一个样本。 -
@MatsPetersson:解决方案是让处理程序保持运行(等待)直到主要完成。如链接问题中所述,当处理程序返回时,它会杀死它。不过,您只有 10 个,这是在 Windows 7+ 中添加的。
标签: c++ winapi console-application