信号是否会中断主线程还是从某些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的答案也是受欢迎的。
答案 0 :(得分:1)
根据文档,Windows不支持SIGINT
。见下文了解更多。
首先,Windows仅支持C规范所需的最小信号。
仅支持那些信号,并且不会发生信号和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
执行此操作。
最后,在信号处理程序中通常只有两件好事可做 - 要么退出(无论如何都是默认行为),要么将消息放在某种队列中以便以后处理(这是大多数高级语言)因为简单的原因,即使不符合规范,信号在行为上也是非常不便携的,并且希望尽可能快地离开处理程序。