1

シグナルはメインスレッドに割り込みますか、それとも OS スレッドから呼び出されますか? つまり、シグナル ハンドラを実装するときにスレッド セーフについて心配する必要はありますか? たとえばon_sigint、別のスレッドで呼び出された場合、次のコードはランダムに失敗します。彼らは?しますか?

#include <csignal>
#include <windows.h>

HANDLE hSigint;

void on_sigint(int sig)
{
    if (hSigint != NULL) SetEvent(hSigint);
    else hSigint = INVALID_HANDLE_VALUE;
}

int wmain(int argc, wchar_t** argv)
{
    hSigint = NULL;
    signal(SIGINT, on_sigint);
    BuildSomething();
    if (hSigint == NULL)
    {
        hSigint = CreateEvent(NULL, TRUE, FALSE, NULL);
        SetSomethingInMotion();
        WaitForSingleObject(hSigint, INFINITE);
    }
    TearSomethingDown();
    return 0;
}

Windows の例ですが、Linux の回答も歓迎します。

4

1 に答える 1

1

ドキュメントによると、SIGINTWindows ではサポートされていません。詳細については、以下を参照してください。

まず、Windows は C 仕様で必要とされる最小限のシグナルのみをサポートします。

  1. SIGABRT 異常終了
  2. SIGFPE 浮動小数点エラー
  3. SIGILL 不正な命令
  4. SIGINT CTRL+C シグナル
  5. SIGSEGV 不正なストレージ アクセス
  6. SIGTERM 終了要求

これらのシグナルのみがサポートされ、シグナルと IO の間の複雑な相互作用は発生しません。たとえばSIGINT、進行中の IO が中止されることはなく、SIGALRM存在しません。

SIGINT第 2に、条件を発生させた同じスレッドで、例外を除くすべてのシグナルが呼び出されます。これは、MSVCRT がこれらのシグナルを SEH を使用した初回例外として実装し、SEH 例外ハンドラーが同じスレッドで実行されるためです。これは、そのような SEH (たとえば、Access Violation が にマップされるSIGSEGV) をEXCEPTION_CONTINUE_SEARCH処理する場合、シグナル関数が呼び出されないことも意味します。

SIGINT一方、 Win32 ではサポートされていません。同等の機能はSetConsoleCtrlHandlerで、これは常に別のスレッドでハンドラー関数を呼び出します。MinGW、Cygwin、または動作する場合は MSVCRT などの使用している CRT が SIGINT を処理する場合、それは常に特別に作成されたスレッド上にあります。

Windows のみのアプリケーションの場合は、SetConsoleCtrlHandler代わりに SEH を使用してください。

別のプロセスにシグナルを送信するのと同等のことをしたい場合は、 でこれを行う必要がありますGenerateConsoleCtrlEvent

最後に、通常、シグナル ハンドラーで行うべき良いことは 2 つだけです。終了する (これが既定の動作です) か、後で処理するために何らかのキューにメッセージを配置します (これは、ほとんどの高級言語が行うことです。仕様になくても、シグナルの動作は非常に移植性が低く、ハンドラーからできるだけ早く抜け出すことが望ましいという単純な理由です。

于 2013-04-08T14:16:45.040 に答える