以下是我在win32上运行的代码。
#include "stdafx.h"
#include <signal.h>
void INThandler( int sig )
{
printf( "Ctrl-C pressed\n" );
}
int main ()
{
signal( SIGINT, INThandler );
while (1)
{
}
return 0;
}
按两次ctrl-c后,程序输出如下。
test.exe中的0x76707577(kernel32.dll)抛出异常:0x40010005:Control-C。
线程0x6a8已退出,代码为0(0x0)。
test.exe中的0x76707577(kernel32.dll)抛出异常:0x40010005:Control-C。
线程0x4104已退出,代码为-1073741510(0xc000013a)。
程序'[14580] test.exe'已退出,代码为-1073741510(0xc000013a)。
我的问题是:为什么我的第二个ctrl-c无法通过我的信号处理功能捕获?我该如何处理这类问题?
我有这个问题,因为我的真实程序占用了大量资源,并且需要很长时间才能释放这些资源。因此,如果在第二个ctrl-c到来时尚未完成释放过程,则会生成一些错误(内存泄漏)。我想避免这种情况。
答案 0 :(得分:2)
来自signal
的文档:
在执行指定函数之前,func的值设置为SIG_DFL。下一个中断信号的处理方式与SIG_DFL相同,除非对信号的干预调用另有规定。
如果要捕获同一信号的第二个实例,则需要在信号处理程序内再次调用signal
。如果在非常繁忙的系统上接收到足够接近的两个中断,这确实引入了潜在的竞争条件。如果您对此感到担心,您可能更愿意使用原生SetConsoleCtrlHandler
函数。
你还应该注意:
任何Win32应用程序都不支持SIGINT。当发生CTRL + C中断时,Win32操作系统会生成一个新线程来专门处理该中断。这可能导致单线程应用程序(例如UNIX中的应用程序)变为多线程并导致意外行为。
尽管如此,使用signal
捕获Control-C实际上是安全的,只要您考虑到从单独的线程调用信号处理程序的事实。但是,如果您希望程序严格遵循Windows,则应使用本机功能。
答案 1 :(得分:0)
我认为问题在于:
来自MSDN
任何Win32应用程序都不支持SIGINT。当发生CTRL + C中断时,Win32操作系统会生成一个新线程 专门处理那个中断。这可能会导致单线程 应用程序,例如UNIX中的应用程序,成为多线程和原因 出乎意料的行为。
因此,您可以更改为其他信号而不是SIGINT
。