Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
326 views
in Technique[技术] by (71.8m points)

c++ - Gracefully terminate a Boost Asio based Windows console application

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_CLOSE, so there is no straightforward way to gracefully close the application externally, e.g. via taskkill. Terminating the process forcibly is not an option. Is there a known approach to this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

" );
      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

" );
      return( TRUE ); 

    // Pass other signals to the next handler. 
    case CTRL_BREAK_EVENT: 
      Beep( 900, 200 ); 
      printf( "Ctrl-Break event

" );
      return FALSE; 

    case CTRL_LOGOFF_EVENT: 
      Beep( 1000, 200 ); 
      printf( "Ctrl-Logoff event

" );
      return FALSE; 

    case CTRL_SHUTDOWN_EVENT: 
      Beep( 750, 500 ); 
      printf( "Ctrl-Shutdown event

" );
      return FALSE; 

    default: 
      return FALSE; 
  } 
} 

int main( void ) 
{ 
  if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) ) 
  { 
    printf( "
The Control Handler is installed.
" ); 
    printf( "
 -- Now try pressing Ctrl+C or Ctrl+Break, or" ); 
    printf( "
    try logging off or closing the console...
" ); 
    printf( "
(...waiting in a loop for events...)

" ); 

    while( 1 ){ } 
  } 
  else 
  {
    printf( "
ERROR: 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...