2014-08-27 93 views
3

我有一个程序,并希望通过发送SIGINT来将某些数据写入文件而不是立即退出来停止它。但是,如果程序的用户再次发送SIGINT,则程序应立即退出,并忘记将数据写入文件。boost :: asio signal_set处理程序仅在第一个信号被捕获后才执行,并忽略同一类型的连续信号

为了便于携带,我想用boost::asio来达到此目的。

我的初始(简化)方法(见下文)不起作用。这是不可能的或者我错过了什么?

处理程序似乎只被调用一次(打印出消息),并且程序在循环达到最大迭代次数时总是停止。

void handler(
const boost::system::error_code& error, 
int signal_number) { 
    if (!error) { 
     static bool first = true; 
     if(first) { 
      std::cout << " A signal(SIGINT) occurred." << std::endl; 
      // do something like writing data to a file 
      first = false; 
     } 
     else { 
      std::cout << " A signal(SIGINT) occurred, exiting...." << std::endl; 
      exit(0); 
     } 
    } 
} 

int main() { 
    // Construct a signal set registered for process termination. 
    boost::asio::io_service io; 
    boost::asio::signal_set signals(io, SIGINT); 

    // Start an asynchronous wait for one of the signals to occur. 
    signals.async_wait(handler); 
    io.run(); 
    size_t i; 

    for(i=0;i<std::numeric_limits<size_t>::max();++i){ 
     // time stepping loop, do some computations 
    } 

    std::cout << i << std::endl; 
    return 0; 
} 

回答

5

当您处理了第一个事件时,您不会在服务对象上发布任何新的工作,因此它会退出。

这意味着然后(在ioservice退出后)启动紧密循环。这可能不是你所期望的。

  1. 如果您想再次听SIGINT,你必须等待从处理程序重新设定信号:

    #include <boost/asio.hpp> 
    #include <boost/asio/signal_set.hpp> 
    #include <boost/bind.hpp> 
    #include <boost/atomic.hpp> 
    #include <iostream> 
    
    void handler(boost::asio::signal_set& this_, boost::system::error_code error, int signal_number) { 
        if (!error) { 
         static boost::atomic_bool first(true); 
         if(first) { 
          // do something like writing data to a file 
          std::cout << " A signal(SIGINT) occurred." << std::endl; 
          first = false; 
    
          this_.async_wait(boost::bind(handler, boost::ref(this_), _1, _2)); 
         } 
         else { 
          std::cout << " A second signal(SIGINT) occurred, exiting...." << std::endl; 
          exit(1); 
         } 
        } 
    } 
    
    int main() { 
        // Construct a signal set registered for process termination. 
        boost::asio::io_service io; 
        boost::asio::signal_set signals(io, SIGINT); 
    
        // Start an asynchronous wait for one of the signals to occur. 
        signals.async_wait(boost::bind(handler, boost::ref(signals), _1, _2)); 
        io.run(); 
        return 2; 
    } 
    

    正如你可以看到我的约束,以便在signal_set&参照处理程序在收到第一个信号后就可以在它上面得到async_wait。另外,作为一个原则问题,我使first成为一个原子(尽管在多线程上运行io_service之前并不需要)。

  2. 您是否确实希望在后台运行io_service?在这种情况下,使它看起来像这样:

    signals.async_wait(boost::bind(handler, boost::ref(signals), _1, _2)); 
    
    boost::thread(boost::bind(&boost::asio::io_service::run, boost::ref(io))).detach(); 
    
    while (true) 
    { 
        std::cout << "Some work on the main thread...\n"; 
        boost::this_thread::sleep_for(boost::chrono::seconds(1)); 
    } 
    

    对于典型的输出:

    Some work on the main thread... 
    Some work on the main thread... 
    Some work on the main thread... 
    ^CSome work on the main thread... 
    A signal(SIGINT) occurred. 
    Some work on the main thread... 
    Some work on the main thread... 
    ^CSome work on the main thread... 
    A second signal(SIGINT) occurred, exiting.... 
    
+0

感谢您的答复,这不仅回答了我原来的问题,但也期待我的下一个问题。如果没有在后台运行io_service,程序就不会停止,如果SIGINT没有发送给进程,显然不是我的预期行为。 – coder 2014-09-02 21:06:05