162

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

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Scott
  • 5,135
  • 12
  • 57
  • 74

4 Answers4

202

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
  • 27,577
  • 7
  • 73
  • 114
Gab Royer
  • 9,587
  • 8
  • 40
  • 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
  • 49
    , 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
  • 10
    `printf()` isn't async-signal-safe, so can't be used inside signal handler. – P.P Jun 28 '16 at 11:09
  • 9
    These functions are not available on Windows. – Timmmm May 29 '17 at 12:32
  • 3
    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
  • 1
    @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
64

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

See here for an example.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Chris Smith
  • 5,326
  • 29
  • 29
49

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
  • 43,810
  • 29
  • 138
  • 169
  • 1
    Yes, it's POSIX. I forgot to add Linux to the question. – Scott Oct 29 '09 at 01:42
  • 4
    signal() behaves differently, depending if it follows BSD or SysV style. sigaction() is preferable. – asveikau Oct 29 '09 at 01:49
  • 9
    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
2

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
  • 16,404
  • 12
  • 44
  • 69
Joyer
  • 371
  • 2
  • 9