标准方式执行与Boost.Asio的干净关闭 [英] standard way to perform a clean shutdown with Boost.Asio

查看:357
本文介绍了标准方式执行与Boost.Asio的干净关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Boost.Asio在C ++中编写了一个跨平台的服务器程序。遵循此网页上的HTTP Server示例,我想处理用户终止请求,而不使用特定于实现的API。我最初试图使用标准的C信号库,但是一直无法找到适合于Asio的设计模式。 Windows示例的设计似乎与信号库最接近,但有一个竞争条件,其中控制台ctrl处理程序可以在服务器对象被销毁后被调用。我试图避免由C ++标准指定的未定义的行为。

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 undefined behavior as specified by the C++ standard.

是否有标准的(正确的)停止服务器的方式?

Is there a standard (and correct) way to stop the server?

为了说明使用C信号库的问题:

To illustrate problems with using the C signal library:

#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
}


推荐答案

Boost.Asio的版本1.5.3(要集成到即将推出的boost 1.47版本中?)具有 signal_set 类:

Version 1.5.3 of Boost.Asio (to be integrated in upcoming boost 1.47 release?) has the signal_set class:

#include <boost/asio/signal_set.hpp>

// Register signal handlers so that the daemon may be shut down. You may
// also want to register for other signals, such as SIGHUP to trigger a
// re-read of a configuration file.
boost::asio::signal_set signals(io_service, SIGINT, SIGTERM);
signals.async_wait(
    boost::bind(&boost::asio::io_service::stop, &io_service));

EDIT

现在,在Boost版本1.47中包括

Now included in Boost version 1.47

这篇关于标准方式执行与Boost.Asio的干净关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆