Этот вопрос основан на следующий вопрос: Handle CTRL+C on Win32Cleanup код в Win32 консольной программы
Я работаю на многопоточном сервере, работающий на Linux и Windows. Я не могу использовать boost или другие фреймворки, только std C++.
У меня проблема с кодом очистки на стороне win32. Линукс работает нормально: когда я хочу завершить работу сервера, я посылаю SIGINT
(с CTRL+C
), обработчик сигнала задает глобальную переменную, а основной pthread выполняет инструкции очистки (объединение других pthreads, освобождение памяти кучи и т. Д.), ,
В окнах это выглядит не так просто, чтобы добиться такого же поведения. Я написал простую тестовую программу, чтобы понять, как обработчики сигналов работают в окнах.
#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, чтобы завершить процесс.
- Return FALSE. Если ни одна из зарегистрированных функций обработчика не возвращает TRUE, обработчик по умолчанию завершает процесс.
- Вернуться ИСТИНА. В этом случае никаких других функций обработки не вызываются, и система прекращает
процесса.
Я пропустил что-то очевидное? Каким образом можно завершить процесс консоли win32 и выполняет код очистки?
Уверены ли вы, что проблемы, которые вы видите, связаны с отсутствием очистки 'cout', на основе того факта, что вы возвращаете« истину »из очистки, поэтому код завершается без вызова флеша, который вы обычно смотрите в 'exit'? –
Просто заменил '' \ n'' на 'std :: endl', результат тот же. – eang
Тогда, боюсь, у меня нет никаких дальнейших предложений. –