I would like to call a cleanup function after the user presses the small "x" at the top right hand corner of the console window.
I have registered an atexit
method but this doesn't get called in this case.
Solution needs to work on windows and linux.
You cannot use atexit here because, it is called when a process is terminated normally, whereas in your case the process is terminated by a signal.
On linux
, SIGHUP (signal hang up) is sent to the process when its controlling terminal is closed, and you can use POSIX signal handling.
On windows
, CTRL_CLOSE_EVENT event is delivered, and you can use SetConsoleCtrlHandler winapi to handle this.
So, to my knowledge, there's no platform independent way to handle this in c++
. You should use platform dependent code to do this as shown in the following simple program. I tested it on windows with VS and on ubuntu with g++. Please note that error handling has been omitted and I/O is performed in signal handlers for simplicity.
The program registers a signal handler and an atexit
function. Then it sleeps for 10 seconds. If you do not close the console within 10s, the process will terminate normally and the atexit
handler will be called. If you close the window before 10s, it'll catch the signal. On linux, you won't see the signal handler getting called, but it does get called, you can check this by writing a file (or issuing a beep?), though I don't recommend it.
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
BOOL sig_handler(DWORD signum)
{
switch( signum )
{
case CTRL_CLOSE_EVENT:
printf( "Ctrl-Close event\n" );
return( TRUE );
default:
return FALSE;
}
}
#else
void sig_handler(int signum)
{
/* you won't see this printed, but it runs */
printf("Received signal %d\n", signum);
}
#endif
void exit_fn(void)
{
printf("%s\n", __FUNCTION__);
}
void setup_signal_handler()
{
#ifdef WIN32
SetConsoleCtrlHandler((PHANDLER_ROUTINE)sig_handler, TRUE);
#else
struct sigaction sa;
sa.sa_handler = &sig_handler;
sigfillset(&sa.sa_mask);
sigaction(SIGHUP, &sa, NULL);
#endif
}
int main(void)
{
printf("%s\n", __FUNCTION__);
/* setup signal handler */
setup_signal_handler();
/* setup function to be called at normal process termination */
atexit(exit_fn);
/* sleep for 10s */
#ifdef WIN32
Sleep(10000);
#else
sleep(10);
#endif
/* print message if process terminates normally */
printf("Normal process termination\n");
exit(EXIT_SUCCESS);
}