Я пишу кроссплатформенную серверную программу на C ++ с использованием Boost.Asio. Следуя примеру HTTP-сервера на этой странице, я хотел бы обрабатывать запрос на завершение работы пользователя без использования API, зависящих от реализации. Я' Сначала мы пытались использовать стандартную библиотеку сигналов C, но не смогли найти шаблон проектирования, подходящий для Asio. Пример Windows , кажется, похож на ближайшую библиотеку сигналов, но есть состояние гонки, при котором обработчик ctrl консоли может быть вызван после того, как объект сервера был уничтожен. Я пытаюсь избежать неопределенного поведения, как указано в стандарте C ++.
Есть ли стандартный (и правильный) способ остановки сервера?
Чтобы проиллюстрировать проблемы с использованием библиотеки сигналов C:
#include
#include
#include
using std::signal;
using boost::asio::io_service;
namespace
{
std::function sighandler;
}
extern "C"
{
static void handle_signal(int);
}
void handle_signal(int)
{
// error - undefined behavior
sighandler();
}
int main()
{
io_service s;
sighandler = std::bind(&io_service::stop, &s);
auto old_sigint = signal(SIGINT, &handle_signal);
if (old_sigint == SIG_IGN)
// race condition? raise SIGINT before I can set ignore back
signal(SIGINT, SIG_IGN);
auto old_sigterm = signal(SIGTERM, &handle_signal);
if (old_sigterm == SIG_IGN)
// race condition? raise SIGTERM before I can set ignore back
signal(SIGTERM, SIG_IGN);
s.run();
// reset signals so I can clear reference to io_service
if (old_sigterm != SIG_IGN)
signal(SIGTERM, SIG_DFL);
if (old_sigint != SIG_IGN)
signal(SIGINT, SIG_DFL);
// clear reference to io_service, but can I be sure that handle_signal
// isn't being executed?
sighandler = nullptr;
// io_service is destroyed
}