Search code examples
c++multithreadingprocessstdin

C++ write to stdin (in Windows)


I have a multi-threaded Windows console app whose control thread runs a user input loop like this:

char c;
do {
    cin >> c;
    // Alter activity based on c
} while(c != 'q')
// Tell other threads to close, .join(), and do cleanup

However at a certain time I want the program itself to be able to gracefully quit. The most obvious way to do so would be to put a "q\n" onto the stdin stream. Is there a reasonable way to do that?

Or a good alternative for a callback to force exit the main control loop (on the primary thread) so that the program falls through to the subsequent cleanup methods?

(The closest I have found so far is this which requires spawning a child process and seems like kludgy overkill at best.)


Solution

  • I ended up using the suggestion from @Captain Obvlious, but even that was tricky (thanks Windows!): As soon as a control signal is handled it causes all sorts of problems with the unchecked char input loop. However, with the following additions any thread can gracefully end the program by calling GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);

    bool exiting = false;
    bool cleanedUp = false;
    void Cleanup() {
        if(!cleanedUp) cleanedUp = true;
        else return;
        // Tell other threads to close, .join(), and do cleanup
    }
    
    // https://msdn.microsoft.com/en-us/library/ms683242(v=vs.85).aspx
    bool ConsoleControl(DWORD dwCtrlType) {
        exiting = true; // This will cause the stdin loop to break
        Cleanup();
        return false;
    }
    
    int main() {
        SetConsoleCtrlHandler((PHANDLER_ROUTINE) ConsoleControl, true);
        .
        .
        .
        // Main user control loop
        char c;
        do {
            cin >> c;
            if(exiting) break;
            if(c < 0) continue; // This must be a control character
            // Alter activity based on c
        } while(c != 'q')
        Cleanup();
        return 0;
    }