Reputation: 67
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?
Upvotes: 4
Views: 2816
Reputation: 393487
Update
Just use any IPC method you would "normally" use
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
Consider making a Windows Service (NTService), as it looks like this is what you want
AllocConsole
or CreateWindow
could help. However, you end up with more platform specific stuffOriginal 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_timer
s).
Once you did that, it should be pretty clean.
Upvotes: 3