Изящно прекратить консольное приложение Windows на основе Boost Asio

Я работаю над HTTP-сервером на основе boost.asio. Предполагается, что он будет остановлен извне. Мы используем обработку сигналов asio, и она хорошо работает для ctrl-c, но не обрабатывает WM_CLOSE, поэтому нет простого способа изящно закрыть приложение снаружи, например, с помощью taskkill. Завершение процесса принудительно — не вариант. Есть ли известный подход к этому?

3

Решение

Обновить

Просто используйте любой метод IPC, который вы обычно используете

  1. Напишите простую утилиту управления процессом, которая использует, например, named_condition чтобы сигнализировать о том, что процесс asio завершен.

    Обратите внимание, что named_codition в некоторой степени эквивалентно именованному событию Win32 на тот случай, если вы считаете, что проще для этой части кода, специфичной для платформы

  2. Рассмотреть вопрос о создании Служба Windows (NTService), как это выглядит, что вы хотите

  3. В общем, попробуйте создать окно верхнего уровня из вашего процесса; Или AllocConsole или же CreateWindow мог бы помочь. Тем не менее, вы в конечном итоге с более конкретной платформой


Оригинальный ответ, Рассмотрим, как прослушивать события закрытия консоли:

Это действительно не связано с использованием 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_timerс).

Как только вы это сделаете, все должно быть довольно чисто.

2

Другие решения


По вопросам рекламы [email protected]