3

我正在开发基于 boost.asio 的 HTTP 服务器。它应该在外部停止。我们使用 asio 信号处理,它适用于 ctrl-c,但不处理 WM_CLOSE,因此没有直接的方法可以从外部优雅地关闭应用程序,例如通过 taskkill。强制终止进程不是一种选择。有没有一种已知的方法来解决这个问题?

4

1 回答 1

2

更新

只需使用您“通常”使用的任何 IPC 方法

  1. 编写一个简单的进程控制实用程序,使用例如named_condition信号通知您的 asio 进程关闭。

    请注意,这named_codition在某种程度上等同于 Win32 命名事件,以防您认为这个固有平台特定的代码更简单

  2. 考虑制作一个Windows 服务 (NTService),因为看起来这就是你想要的

  3. 从长远来看,尝试从您的流程中创建一个顶级窗口;要么AllocConsoleCreateWindow可以提供帮助。但是,您最终会得到更多特定于平台的东西



原始答案,处理如何监听控制台关闭事件:

这实际上与使用 Boost Asio 无关。当然,在 POSIX 平台上,您可以boost::asio::signal_set用来处理 SIG_INT 和 SIG_TERM 信号。

但是,您在 Windows 上,并且没有可移植的方法来检测控制台关闭事件。

您应该编写一个检测 CTRL_CLOSE_EVENT(和 CTRL_C_EVENT,如果需要)的控制台处理程序例程,并使用 SetConsoleCtrlHandler 将处理程序例程添加到您的进程中。

#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;
}

要与 Boost Asio 协调,您可以让处理程序停止(全局)io_service 对象,并可能为运行操作设置一些标志。最后,您可能必须取消任何运行中的异步操作(例如deadline_timers)。

一旦你这样做了,它应该很干净。

于 2014-10-16T13:14:32.863 回答