Estoy escribiendo un programa de servidor multiplataforma en C++ usando Boost.Asio. Siguiendo el ejemplo del Servidor HTTP en this page, me gustaría gestionar una solicitud de terminación de usuario sin utilizar API específicas de la implementación. Inicialmente intenté usar la biblioteca de señales C estándar, pero no he podido encontrar un patrón de diseño adecuado para Asio. El diseño Windows example's parece asemejarse a la biblioteca de señal más cercana, pero hay una condición de carrera donde se podría llamar al controlador ctrl de consola después de que el objeto del servidor haya sido destruido. Estoy tratando de evitar el comportamiento indefinido según lo especificado por el estándar de C++.manera estándar de realizar un apagado limpio con Boost.Asio
¿Existe una forma estándar (y correcta) para detener el servidor?
Para ilustrar los problemas con el uso de la biblioteca señal 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
}
@Timothy ¿Estás preguntando cómo instalar un manejador de señal para una señal como SIGINT? O bien, ¿qué hacer en ese controlador de señal para apagar su servidor HTTP? –
@Sam agregó un ejemplo de diseño de la firma – Timothy003
@Timothy no se puede invocar '' io_service :: stop' de forma segura desde su manejador de señal, incluso si está envuelto en una función 'boost ::. Hacerlo da como resultado un comportamiento indefinido. Mire [mi respuesta] (http://stackoverflow.com/questions/4639909/standard-way-to-perform-a-clean-shutdown-with-boost-asio/4639977#4639977) para obtener una lista de funciones que puede llamar desde dentro de un manejador de señal. –