Gracefully terminate a Boost Asio based Windows console application

前端 未结 1 778
独厮守ぢ
独厮守ぢ 2020-12-11 09:27

I am working on a boost.asio based HTTP server. It is supposed to be stopped externally. We use asio signal handling, and it works well for ctrl-c, but does not handle WM_CL

相关标签:
1条回答
  • 2020-12-11 10:03

    Update

    Just use any IPC method you would "normally" use

    1. Write a simple process control utility that uses e.g. named_condition to signal your asio process to shutdown.

      Note that named_codition is somewhat equivalent to a Win32 Named Event in case you think that simpler for this inherently platform specific piece of code

    2. Consider making a Windows Service (NTService), as it looks like this is what you want

    3. As a long shot, try to create a toplevel window from your process; Either AllocConsole or CreateWindow could help. However, you end up with more platform specific stuff



    Original answer, dealing with how to listen for console close events:

    This is really not related to using Boost Asio. Of course, on POSIX platforms you could use boost::asio::signal_set to handle the SIG_INT and SIG_TERM signals.

    However, you're on windows, and there is no portable way to detect console close event.

    You should write a console handler routine that detects CTRL_CLOSE_EVENT (and CTRL_C_EVENT, if desired), and use SetConsoleCtrlHandler to add the handler routine to your process.

    #include <windows.h> 
    #include <stdio.h> 
    
    BOOL CtrlHandler( DWORD fdwCtrlType ) 
    { 
      switch( fdwCtrlType ) 
      { 
        // Handle the CTRL-C signal. 
        case CTRL_C_EVENT: 
          printf( "Ctrl-C event\n\n" );
          Beep( 750, 300 ); 
          return( TRUE );
    
        // CTRL-CLOSE: confirm that the user wants to exit. 
        case CTRL_CLOSE_EVENT: 
          Beep( 600, 200 ); 
          printf( "Ctrl-Close event\n\n" );
          return( TRUE ); 
    
        // Pass other signals to the next handler. 
        case CTRL_BREAK_EVENT: 
          Beep( 900, 200 ); 
          printf( "Ctrl-Break event\n\n" );
          return FALSE; 
    
        case CTRL_LOGOFF_EVENT: 
          Beep( 1000, 200 ); 
          printf( "Ctrl-Logoff event\n\n" );
          return FALSE; 
    
        case CTRL_SHUTDOWN_EVENT: 
          Beep( 750, 500 ); 
          printf( "Ctrl-Shutdown event\n\n" );
          return FALSE; 
    
        default: 
          return FALSE; 
      } 
    } 
    
    int main( void ) 
    { 
      if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) ) 
      { 
        printf( "\nThe Control Handler is installed.\n" ); 
        printf( "\n -- Now try pressing Ctrl+C or Ctrl+Break, or" ); 
        printf( "\n    try logging off or closing the console...\n" ); 
        printf( "\n(...waiting in a loop for events...)\n\n" ); 
    
        while( 1 ){ } 
      } 
      else 
      {
        printf( "\nERROR: Could not set control handler"); 
        return 1;
      }
    return 0;
    }
    

    To coordinate with Boost Asio, you could have the handler stop the (global) io_service object and perhaps set some flag for running actions. Finally, you may have to cancel any async operations in flight (e.g. deadline_timers).

    Once you did that, it should be pretty clean.

    0 讨论(0)
提交回复
热议问题