哪个线程是信号处理程序(例如信号(SIGINT,crtl_c);)被调用?

时间:2013-04-08 12:42:56

标签: signals

信号是否会中断主线程还是从某些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的答案也是受欢迎的。

1 个答案:

答案 0 :(得分:1)

根据文档,Windows不支持SIGINT。见下文了解更多。

首先,Windows仅支持C规范所需的最小信号。

  1. SIGABRT异常终止
  2. SIGFPE浮点错误
  3. SIGILL非法指令
  4. SIGINT CTRL + C signal
  5. SIGSEGV非法存储访问
  6. SIGTERM终止请求
  7. 仅支持那些信号,并且不会发生信号和IO之间的复杂交互 - 例如SIGINT不会导致正在进行的IO中止,并且SIGALRM不存在。

    其次,除了SIGINT之外的所有信号都在同一个线程上调用,这引起了条件。这是因为MSVCRT使用SEH将这些信号实现为第一次机会异常,并且SEH异常处理程序在同一线程上运行。这也意味着如果您使用SIGSEGV以外的任何其他方式处理此类SEH(例如,访问冲突映射到EXCEPTION_CONTINUE_SEARCH),则不会调用信号函数。

    另一方面,

    SIGINT 在Win32 上不受支持。等效功能是SetConsoleCtrlHandler,它总是在不同的线程上调用处理函数。如果你正在使用的CRT,如MinGW,Cygwin,或者,如果它工作,MSVCRT,处理SIGINT,它将始终在一个特殊创建的线程上。

    如果是仅限Windows的应用程序,请使用SetConsoleCtrlHandler和SEH。

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

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