哪个线程是调用的信号处理程序(例如signal(SIGINT,crtl_c);)?
信号是否会中断主线程,还是从某个操作系统线程调用?换句话说,在执行信号处理程序时,我是否必须担心线程安全?例如,如果在单独的线程上调用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的答案也很受欢迎。
根据文档,Windows不支持SIGINT
。请参阅下文了解更多。
首先,Windows只支持C规范所需的最小信号。
- SIGABRT异常终止
- SIGFPE浮点错误
- SIGILL非法指令
- SIGINT CTRL + C信号
- SIGSEGV非法存储访问
- 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
做到这一点。
最后,在信号处理程序中通常只有两件好事 - 退出(无论如何都是默认行为),或者将消息放入某种队列中供以后处理(这是最高级别语言是这样做的,原因很简单,即使不符合规范,信号在行为上也是非常不可移植的,并且希望尽可能快地离开处理程序。
嗯,但在Windows中支持SIGINT * *。我刚刚写了一个成功应用它的应用程序。当我在处理程序中设置断点时,运行应用程序,然后按Crtl + C,它按预期在处理程序中中断。 – 2013-04-08 16:12:29
@AnsisMalins,好吧,我错误地理解了文档!我可以告诉你,Ctrl + C由SetConsoleCtrlHandler处理,所以你的CRT必须使用它。我认为***是*** MSVCRT而不是MinGW或Cygwin? – Ben 2013-04-08 16:41:39
@AnsisMalins,更新了答案。 Ctr + C将始终在单独的线程中调用。 Ctrl + Break和窗口关闭按钮(如果它们作为信号处理)也将在单独的线程中调用,因为它们以相同的方式实现。 – Ben 2013-04-08 16:44:59
您使用MSVCRT吗? – Ben 2013-04-08 16:45:17
我这么认为。我正在使用Visual Studio 2012. – 2013-04-08 22:22:42