Я пишу кросс-платформенную серверную программу на С++, используя Boost.Asio. Следуя примеру HTTP-сервера на этой страницы, Я бы хотел обработать запрос на завершение работы пользователя без использования API-интерфейсов для реализации, Сначала я попытался использовать стандартную библиотеку сигналов C, но не смог найти шаблон дизайна, подходящий для Asio. Пример проекта в стиле Windows, похоже, напоминает библиотека сигналов ближе всего, но есть условие гонки, в котором консольный обработчик ctrl может быть вызван после уничтожения объекта сервера. Я пытаюсь избежать поведения undefined, как указано в стандарте С++.
Есть ли стандартный (и правильный) способ остановить сервер?
Чтобы проиллюстрировать проблемы с использованием библиотеки сигналов C:
#include <csignal>
#include <functional>
#include <boost/asio.hpp>
using std::signal;
using boost::asio::io_service;
namespace
{
std::function<void ()> 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
}