3

Okay, I am writing a program that is doing some pretty heavy analysis and I would like to be able to stop it quickly.

I added signal(SIGINT, terminate); to the beginning of main and defined terminate like:

void terminate(int param){
   cout << endl << endl << "Exit [N]ow, or [A]fter this url?" << endl;
   std::string answer;
   cin >> answer;
   if(answer[0] == 'n' || answer[0] == 'N'){
      terminateParser();
      exit(1);
   }else if(answer[0] == 'a' || answer[0] == 'A'){
      quitAfterUrl = true;
   }
}

In linux, this worked as I expected it to, that is it waited for user input. But when I try to do the same in windows, it shows the message and exits anyway.

Is there any way to stop SIGINT from closing the program immediately?

Update:

when I tried

BOOL WINAPI handler(DWORD dwCtrlType)
{
  if (CTRL_C_EVENT == dwCtrlType)
  {
    // ask the user
  }
  return FALSE;
}

as Gregory suggested, the program still unceremoniously exited without stopping for user input.

Update 2: I am not exactly sure what did it, but the code is working now. Thank you all for the help.

Jolta
  • 2,620
  • 1
  • 29
  • 42
zmbush
  • 2,790
  • 1
  • 17
  • 35
  • Not exactly solving your question - but if you can (and because you wrote for linux initially), you can try to compile with gcc on windows - the behaviour seen might resemble the linux one closer. See the MinGw website. Also - cygwin brings programming even closer to unix than mingw. – laura Jan 09 '10 at 00:37
  • did you call `SetConsoleCtrlHandler(handler, TRUE);` ? at the beginning of `main` ? – Gregory Pakosz Jan 09 '10 at 01:11
  • Yes, the program enters the handler function, runs the cout command, and then skips the cin and exits. – zmbush Jan 09 '10 at 01:17
  • hmm yeah looks like `stdin` is already closed at this point – Gregory Pakosz Jan 09 '10 at 01:24
  • Thanks anyway, I think I'll try a different tactic. – zmbush Jan 09 '10 at 01:34
  • try `std::cin.clear();` at the beginning of your handler or since you're writing win32 specific code already for the handler, you could use `MessageBox(NULL, "Are you sure?", "CTRL+C trapped", MB_YESNO);` – Gregory Pakosz Jan 09 '10 at 01:36
  • I have tried many methods to get this to work, and the one thing I have noticed is that the handler does not execute more that one line of code. That is, when I call `std::cout` twice, the second call doesn't execute. – zmbush Jan 09 '10 at 01:55
  • 1
    Note that `sigaction` is much preferred to `signal` for portable programs, because the latter has different historic behavior on different UNIXes. – ephemient Jan 09 '10 at 07:50

1 Answers1

8

From MSDN:

Note SIGINT is not supported for any Win32 application, including Windows 98/Me and Windows NT/2000/XP. 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 UNIX, to become multithreaded, resulting in unexpected behavior.

Which means you will have to use preprocessing directive and implement a Windows specific solution.

BOOL WINAPI handler(DWORD dwCtrlType)
{
  if (CTRL_C_EVENT == dwCtrlType)
  {
    // ask the user
  }
  return FALSE;
}

And at the beginning of main you do

SetConsoleCtrlHandler(handler, TRUE);
Gregory Pakosz
  • 69,011
  • 20
  • 139
  • 164
  • As a note: is his situation allows, compiling with gcc for windows might prevent the rewrite of the solution. – laura Jan 09 '10 at 00:38
  • I guess this is my best option. – zmbush Jan 09 '10 at 00:45
  • I don't recall any other way and well the note about `SIGINT` makes it pretty clear – Gregory Pakosz Jan 09 '10 at 01:09
  • I usually have a common SIGINT stub for both Windows and other operating systems. This way, I'm able to call the common stub from the various OS-specific event handlers and avoid code duplication. – Matthew Iselin Jan 09 '10 at 01:20
  • I have been running this application from MSYS with MinGW32. but when i tried it under windows command prompt, it worked fine. thank you. – zmbush Jan 09 '10 at 02:15