この質問は次の質問に基づいています: Win32 で CTRL+C を処理する
Linux と Windows で実行されているマルチスレッド サーバーで作業しています。ブーストやその他のフレームワークは使用できず、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
そのため、メイン スレッドは 2 つの命令の後でのみすぐに強制終了されます。前の質問での提案の 1 つは、クリーンアップ コードをハンドラーに移動することでしたが、実際には役に立ちません。
ハンドラー関数が次のようになっているとします。
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 を返さない場合、デフォルトのハンドラーはプロセスを終了します。
- TRUE を返します。この場合、他のハンドラ関数は呼び出されず、システムは終了します
プロセス。
明らかな何かが欠けていますか?win32 コンソール プロセスを終了し、そのクリーンアップ コードを実行する適切な方法は何ですか?