-1

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.

Jacko
  • 12,665
  • 18
  • 75
  • 126
  • 1
    What is the language/platform? What app should be called on this event? is it like an app running in the console should be notified, or some outside app? – Alex Butenko Dec 21 '17 at 06:21
  • 1
    `console exit trap` ... alright ... `platform independant` im listening `click the small x` do you mean the _platform independant_ small x? – Jake H Dec 23 '17 at 03:13

1 Answers1

1

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);
}
dhanushka
  • 10,492
  • 2
  • 37
  • 47
  • Excellent! Thank you very much. – Jacko Dec 24 '17 at 13:39
  • Works like a charm. Thank you again! This solves a problem I have been having for at least a year now. – Jacko Dec 24 '17 at 18:15
  • @Jacko Glad that it helped :) – dhanushka Dec 25 '17 at 00:45
  • One addendum: I found that it was useful to add handlers for CTRL_C_EVENT: CTRL_BREAK_EVENT: and CTRL_SHUTDOWN_EVENT: for the windows signal handler. because these are also events that I would like to handle. – Jacko Dec 26 '17 at 01:37