149

How do I catch a Ctrl+C event in C++?

Uwe Keim
  • 38,279
  • 56
  • 171
  • 280
Scott
  • 4,925
  • 12
  • 54
  • 73

4 Answers4

187

signal isn't the most reliable way as it differs in implementations. I would recommend using sigaction. Tom's code would now look like this :

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

void my_handler(int s){
           printf("Caught signal %d\n",s);
           exit(1); 

}

int main(int argc,char** argv)
{

   struct sigaction sigIntHandler;

   sigIntHandler.sa_handler = my_handler;
   sigemptyset(&sigIntHandler.sa_mask);
   sigIntHandler.sa_flags = 0;

   sigaction(SIGINT, &sigIntHandler, NULL);

   pause();

   return 0;    
}
auselen
  • 26,672
  • 5
  • 70
  • 110
Gab Royer
  • 9,199
  • 8
  • 37
  • 58
  • 1
    I think my_handler should take `int s` as it's argument. `sig_t` is itself a function pointer type. – Matthew Marshall Mar 10 '10 at 16:34
  • 42
    , etc - it's C, not C++. In C++ you should use – Abyx Sep 19 '10 at 11:59
  • Works on OSX. In my main.mm file, I didn't even need to include signal.h, stdlib.h, or unistd.h. I just included stdio.h and Foundation/Foundation.h, and then if I needed to do std::cout stuff for outputting a shutdown message, I included iostream. – Volomike Mar 31 '16 at 18:03
  • 9
    `printf()` isn't async-signal-safe, so can't be used inside signal handler. – P.P Jun 28 '16 at 11:09
  • 8
    These functions are not available on Windows. – Timmmm May 29 '17 at 12:32
  • 2
    would be nice to have some explanation about `sa_mask` and `sa_flags`. – qed Nov 21 '18 at 10:52
  • 1
    @Timmmm No doubt you've figured it out by now, but for anyone else wondering: these are posix calls, which work on Linux and Unix systems. For windows you have to use the windows api. – FelisPhasma Mar 15 '19 at 20:16
  • @FelisPhasma: Being Posix doesn't really have much to do with it. Windows includes support for a decent number of Posix functions. – Timmmm Mar 18 '19 at 14:09
60

For a Windows console app, you want to use SetConsoleCtrlHandler to handle CTRL+C and CTRL+BREAK.

See here for an example.

Uwe Keim
  • 38,279
  • 56
  • 171
  • 280
Chris Smith
  • 5,064
  • 27
  • 28
45

You have to catch the SIGINT signal (we are talking POSIX right?)

See @Gab Royer´s answer for sigaction.

Example:

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

void my_handler(sig_t s){
           printf("Caught signal %d\n",s);
           exit(1); 

}

int main(int argc,char** argv)
{
   signal (SIGINT,my_handler);

   while(1);
   return 0;

}
Tom
  • 41,802
  • 29
  • 133
  • 165
  • Yes, it's POSIX. I forgot to add Linux to the question. – Scott Oct 29 '09 at 01:42
  • 3
    signal() behaves differently, depending if it follows BSD or SysV style. sigaction() is preferable. – asveikau Oct 29 '09 at 01:49
  • 5
    I know it is old, but this does not compile in g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0. I had to change `void my_handler(sig_t s)` to `void my_handler(sig_atomic_t s)`. – jcmonteiro Sep 09 '19 at 20:07
1

Yeah, this is a platform dependent question.

If you are writing a console program on POSIX, use the signal API (#include <signal.h>).

In a WIN32 GUI application you should handle the WM_KEYDOWN message.

Werner Henze
  • 15,667
  • 12
  • 43
  • 65
Joyer
  • 361
  • 2
  • 9