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都在引起该条件的同一线程上调用。这是因为 MSVCRT 使用 SEH 将这些信号作为第一次机会异常实现,并且 SEH 异常处理程序在同一线程上运行。这也意味着,如果您处理这样的 SEH(例如 Access Violation 映射到SIGSEGV),EXCEPTION_CONTINUE_SEARCH那么信号函数将不会被调用。

SIGINT另一方面,在 Win32 上不受支持。等效的功能是SetConsoleCtrlHandler,它总是在不同的线程上调用处理函数。如果您使用的 CRT(例如 MinGW、Cygwin 或 MSVCRT(如果可以)处理 SIGINT)将始终位于专门创建的线程上。

如果它是仅 Windows 应用程序使用SetConsoleCtrlHandler和 SEH 代替。

如果您希望执行相当于向另一个进程发送信号的操作,您应该使用GenerateConsoleCtrlEvent.

最后,在信号处理程序中通常只有两件好事要做 - 要么退出(无论如何这是默认行为),或者将消息放在某种队列中以供以后处理(这是大多数高级语言所做的,因为一个简单的原因是,即使不在规范中,信号在行为上也是高度不可移植的,并且希望尽快离开处理程序。

于 2013-04-08T14:16:45.040 回答