2013-04-08 26 views
0

信号是否会中断主线程,还是从某个操作系统线程调用?换句话说,在执行信号处理程序时,我是否必须担心线程安全?例如,如果在单独的线程上调用on_sigint,以下代码将随机失败。他们?会吗?哪个线程是调用的信号处理程序(例如signal(SIGINT,crtl_c);)?

#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的答案也很受欢迎。

+0

您使用MSVCRT吗? – Ben 2013-04-08 16:45:17

+0

我这么认为。我正在使用Visual Studio 2012. – 2013-04-08 22:22:42

回答

1

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

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

  1. SIGABRT异常终止
  2. SIGFPE浮点错误
  3. SIGILL非法指令
  4. SIGINT CTRL + C信号
  5. SIGSEGV非法存储访问
  6. SIGTERM终止请求

只有那些信号被支持,并且复杂的交互信号和IO之间的切换不会发生 - 例如SIGINT不会导致正在进行的IO中止,并且SIGALRM不存在。

其次,除了SIGINT所有信号被称为这引起了条件相同的线程上。这是因为MSVCRT使用SEH将这些信号实现为第一偶然异常,并且SEH异常处理程序在同一个线程上运行。这也意味着,如果你比EXCEPTION_CONTINUE_SEARCH任何其他处理这样的SEH(如访问冲突映射到SIGSEGV),则信号函数将不会被调用。

SIGINT另一方面是不支持Win32。等价的功能是SetConsoleCtrlHandler,它总是在不同的线程上调用处理函数。如果您正在使用的CRT如MinGW,Cygwin,或者如果它有效,MSVCRT处理SIGINT,它将始终位于特制的线程上。

如果它是一个仅适用于Windows应用程序中使用SetConsoleCtrlHandler和SEH来代替。

如果你希望做将信号发送到另一个进程的等值金额,您应该GenerateConsoleCtrlEvent做到这一点。

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

+0

嗯,但在Windows中支持SIGINT * *。我刚刚写了一个成功应用它的应用程序。当我在处理程序中设置断点时,运行应用程序,然后按Crtl + C,它按预期在处理程序中中断。 – 2013-04-08 16:12:29

+0

@AnsisMalins,好吧,我错误地理解了文档!我可以告诉你,Ctrl + C由SetConsoleCtrlHandler处理,所以你的CRT必须使用它。我认为***是*** MSVCRT而不是MinGW或Cygwin? – Ben 2013-04-08 16:41:39

+1

@AnsisMalins,更新了答案。 Ctr + C将始终在单独的线程中调用。 Ctrl + Break和窗口关闭按钮(如果它们作为信号处理)也将在单独的线程中调用,因为它们以相同的方式实现。 – Ben 2013-04-08 16:44:59