4

Below is my code to run on 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;
}

The output of the program is as follows after I press ctrl-c twice.

Exception thrown at 0x76707577 (kernel32.dll) in test.exe: 0x40010005: Control-C.

The thread 0x6a8 has exited with code 0 (0x0).

Exception thrown at 0x76707577 (kernel32.dll) in test.exe: 0x40010005: Control-C.

The thread 0x4104 has exited with code -1073741510 (0xc000013a).

The program '[14580] test.exe' has exited with code -1073741510 (0xc000013a).

My question is: why my second ctrl-c can't be captured by my signal processing function? How should I process this kind of issues?

I have this problem since my real program takes a lot of resource and it takes a long time to release those resource. So if the release process has not been done while the 2nd ctrl-c comes, some errors (memory leak) will be generated. I want to avoid this.

yazou
  • 51
  • 4

2 Answers2

3

From the documentation for signal :

Before the specified function is executed, the value of func is set to SIG_DFL. The next interrupt signal is treated as described for SIG_DFL, unless an intervening call to signal specifies otherwise.

You need to call signal again inside the signal handler if you want to capture a second instance of the same signal. This does introduce a potential race condition if two interrupts are received in sufficiently close proximity on a very busy system. If you are concerned about this you might prefer to use the native SetConsoleCtrlHandler function instead.

You should also note:

SIGINT is not supported for any Win32 application. When a CTRL+C interrupt occurs, Win32 operating systems generate a new thread to specifically handle that interrupt. This can cause a single-thread application, such as one in UNIX, to become multithreaded and cause unexpected behavior.

Despite this, it is in practice safe to use signal to capture Control-C, provided that you take into account the fact that the signal handler is called from a separate thread. However, if you prefer that your program be strictly Windows-compliant, you should use the native functionality instead.

Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
  • Thanks for your quick reply. If I want my code running on both win32 and linux, could you provide some more suggestion? – yazou May 14 '17 at 05:02
  • So far as I can see, there's nothing preventing you from calling `signal` inside the signal handler in Linux. So that will work on both operating systems. – Harry Johnston May 14 '17 at 08:35
  • Is it required to call signal again inside the signal handler on linux if I want to capture a second instance of the same signal? – yazou May 14 '17 at 09:51
  • Apparently that depends on the compiler settings, but from what I can tell it usually isn't necessary. However, that doesn't mean that you can't do so, I don't see any indication that it would cause any harm. – Harry Johnston May 14 '17 at 21:13
1

I think the problem is that :

From MSDN

SIGINT is not supported for any Win32 application. When a CTRL+C interrupt occurs, Win32 operating systems generate a new thread to specifically handle that interrupt. This can cause a single-thread application, such as one in UNIX, to become multithreaded and cause unexpected behavior.


So , may be you can change to other signal instead of SIGINT.

Mattia Dinosaur
  • 891
  • 10
  • 29
  • Since the OP wants to deal with the case where the user presses Control-C, it isn't practical to use a different signal. Besides, SIGINT is the only signal on Windows that can be generated externally, all of the others can only be raised from inside the process. – Harry Johnston May 14 '17 at 03:48