I'm writing a cross-platform server program in C++ using Boost.Asio. Following the HTTP Server example on this page, I'd like to handle a user termination request without using implementation-specific APIs. I've initially attempted to use the standard C signal library, but have been unable to find a design pattern suitable for Asio. The Windows example's design seems to resemble the signal library closest, but there's a race condition where the console ctrl handler could be called after the server object has been destroyed. I'm trying to avoid race conditions that cause undefined behavior as specified by the C++ standard.
Is there a standard (correct) way to stop the server?
So far:
#include <csignal>
#include <functional>
#include <boost/asio.hpp>
using std::signal;
using boost::asio::io_service;
extern "C"
{
static void handle_signal(int);
}
namespace
{
std::function<void ()> sighandler;
}
void handle_signal(int)
{
sighandler();
}
int main()
{
io_service s;
sighandler = std::bind(&io_service::stop, &s);
auto res = signal(SIGINT, &handle_signal);
// race condition? SIGINT raised before I could set ignore back
if (res == SIG_IGN)
signal(SIGINT, SIG_IGN);
res = signal(SIGTERM, &handle_signal);
// race condition? SIGTERM raised before I could set ignore back
if (res == SIG_IGN)
signal(SIGTERM, SIG_IGN);
s.run();
// reset signals
signal(SIGTERM, SIG_DFL);
signal(SIGINT, SIG_DFL);
// is it defined whether handle_signal can still be in execution at this
// point?
sighandler = nullptr;
}