Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Graceful exit when closing console window

I'm trying to make a graceful exit from a console app when the close button is hit.

bool done = false;

BOOL ctrl_handler(DWORD event)
{
    if (event == CTRL_CLOSE_EVENT) {
        done = true;
        return TRUE;
    }
    return FALSE;
}

int main()
{
    SetConsoleCtrlHandler((PHANDLER_ROUTINE)(ctrl_handler), TRUE);

    while (!done)
        do_stuff();

    cleanup();
    cout << "bye";
}

My handler gets called properly but the main thread does not resume afterwards so the "bye" never happens. If I trap CTRL_C_EVENT instead and hit ^C in the console then the main thread is allowed to continue and exits gracefully. Is there some way to allow the main thread to exit gracefully on console close?

I've also tried using std::signal but it's the same. Works for ^C but not for window close.

like image 710
tukra Avatar asked Feb 18 '15 23:02

tukra


2 Answers

Thanks Jonathan for the tip.

I saw that the handler is called on it's own thread. If the handler returns then the whole process is forced to exit so we need to give the main thread time to exit on its own.

bool done = false;

BOOL ctrl_handler(DWORD event)
{
    if (event == CTRL_CLOSE_EVENT) {
        done = true;
        Sleep(20000); // force exit after 20 seconds
        return TRUE;
    }
    return FALSE;
}

int main()
{
    SetConsoleCtrlHandler((PHANDLER_ROUTINE)(ctrl_handler), TRUE);

    while (!done)
        do_stuff();

    cleanup();
    cout << "bye";
}
like image 112
tukra Avatar answered Nov 08 '22 01:11

tukra


I think the better way would be to use:

if (event == CTRL_CLOSE_EVENT)
{
    ExitThread(0);
//  return TRUE; // warning C4702: unreachable code
}

The ExitThread will terminate the thread from which ctrl_handler gets called. This way ExitProcess will not be called, and your main thread will be able to perform all the needed cleanup.

like image 25
Gediminas Avatar answered Nov 08 '22 00:11

Gediminas