为什么在win32上无法捕获第二个SIGINT?

时间:2017-05-14 01:22:42

标签: winapi sigint

以下是我在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到来时尚未完成释放过程,则会生成一些错误(内存泄漏)。我想避免这种情况。

2 个答案:

答案 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