【问题标题】:Boost basic_deadline_timer stops triggering after a few iterationsBoost basic_deadline_timer 在几次迭代后停止触发
【发布时间】:2016-02-02 06:22:13
【问题描述】:

我继承了一个项目,我正在努力思考一切如何 作品。我已经检查了我在截止日期计时器中遇到的所有基本问题 之前。

  • 在调用io_service.run 之前,我们是否附加了一个工作对象? ☑
  • 对象是否保持活动状态并在范围内? ☑
  • 确认我们没有收到错误代码? ☑

*** 新数据 **************

它不只是在杂草中消失,它确实会回来并像往常一样恢复运作。但它需要大约 5 到 10 分钟。计时器本身似乎是基于滴答计数计时器示例:

http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/example/timers/tick_count_timer.cpp

此时我想知道计时器对象本身是否有问题。我一直使用正常的截止日期计时器。我认为它使用 tick_count_timer 独立于系统时钟,系统时钟通常从属于某个地方的网络时钟。

这不是计时器重新启动的情况,因为有一个单独的路径,我没有第二次看到该打印输出。

*** 结束新数据 *********

不用说这让我很难过。

这是有问题的方法:

void project::on_heartbeatsend_timer_elapsed(const boost::system::error_code& e)
{
    if (e != boost::asio::error::operation_aborted)
    {
        if (this->m_state!=session_state::SessionConnected)
        {
            stop("Heartbeat SEND lost connection");

#ifdef HEARTBEAT_DEBUG
            cout << "Heartbeat SEND lost connection to target: "
                << GetIP().c_str()
                << ":"
                << GetPort()
                << endl;
#endif // HEARTBEAT_DEBUG

        }
        else
        {

            size_t size = 0;
            packet_buffer_t b(construct_api_packet(SESSION_HEARTBEAT, 0, 0,NULL,size,&size));
            write(b, size);

            m_timerHeartbeatSend.cancel();

            size_t cancelled_stuff = m_timerHeartbeatSend.expires_from_now(m_heartbeatFrequency*1000);

            m_timerHeartbeatSend.async_wait(strand_.wrap(boost::bind(&project::on_heartbeatsend_timer_elapsed, 
                            shared_from_this(),
                            boost::asio::placeholders::error)));
#ifdef HEARTBEAT_DEBUG
            cout << "Heartbeat SEND to target "
                << GetIP().c_str()
                << ":"
                << GetPort()
                << " Next Heartbeat in: "
                << m_heartbeatFrequency
                << " seconds. cancelled "
                << cancelled_stuff
                << " pending operation."
                << endl;
#endif // HEARTBEAT_DEBUG
        }
    }
    else if (e.value() != 995)
    {
        stringstream evalSS;
        evalSS << e.value();

        std::string error_str = std::string("Error in on_heartbeatsend_timer_elapsed: ") + e.message() + " (" + evalSS.str() + ")";

        stop(error_str);

#ifdef HEARTBEAT_DEBUG
        cout << "Heartbeat "
            << error_str.c_str()
            << "   "
            << GetIP().c_str()
            << ":"
            << GetPort()
            << endl;
#endif // HEARTBEAT_DEBUG
    }
    else
    {
#ifdef HEARTBEAT_DEBUG
        cout << "Heartbeat Threading ending to target "
            << GetIP().c_str()
            << ":"
            << GetPort()
            << endl;
#endif // HEARTBEAT_DEBUG
    }
#ifdef HEARTBEAT_DEBUG
    cout << "finished processing this heartbeat for sending to target "
        << GetIP().c_str()
        << ":"
        << GetPort()
        << endl;
#endif
}

调试的输出如下:

Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50647
Heartbeat SEND to target 127.0.0.1:50647 Next Heartbeat in: 5 seconds. cancelled 0 pending operation.
finished processing this heartbeat for sending to target 127.0.0.1:50647
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50647
Heartbeat SEND to target 127.0.0.1:50647 Next Heartbeat in: 5 seconds. cancelled 0 pending operation.
finished processing this heartbeat for sending to target 127.0.0.1:50647
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50647
Heartbeat SEND to target 127.0.0.1:50647 Next Heartbeat in: 5 seconds. cancelled 0 pending operation.
finished processing this heartbeat for sending to target 127.0.0.1:50647
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50647
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50647
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50647
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50647
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50647
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50647
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50647
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50647

Heartbeat RECV timer STARTED 消息在每次触发时启动 心跳包是从 C# 测试器接收到的,用于 C# 实现 API。

接下来我想做的是在调试器中进一步检查。我在用着 Visual Studio 2013,但我很难做出正面或反面 m_timerHeartbeatSend 对象。

添加了更多调试,以显示我看到的更好的模式。时间戳是滴答计数。

Heartbeat SEND to target 127.0.0.1:50367 Next Heartbeat in: 5 seconds. cancelled
 0 pending operation. old experation: 1672369 now expires at: 1677377 current ti
me: 1672377
finished processing this heartbeat for sending to target 127.0.0.1:50367
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1677307
Heartbeat SEND to target 127.0.0.1:50367 Next Heartbeat in: 5 seconds. cancelled
 0 pending operation. old experation: 1677377 now expires at: 1682385 current ti
me: 1677385
finished processing this heartbeat for sending to target 127.0.0.1:50367
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1682299
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1687306
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1692314
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1697322
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1702314
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1707321
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1712329
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1717337
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1722344
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1727352
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1732344
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1737351
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1742359
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1747367
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1752374
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1757366
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1762374
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1767382
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1772389
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1777397
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1782405
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1787412
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1792404
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1797412
Heartbeat SEND to target 127.0.0.1:50367 Next Heartbeat in: 5 seconds. cancelled
 0 pending operation. old experation: 1682385 now expires at: 1805001 current ti
me: 1800001
finished processing this heartbeat for sending to target 127.0.0.1:50367
Heartbeat RECV timer STARTED (handle_read_header) for target 127.0.0.1:50367 at
1802419
Heartbeat SEND to target 127.0.0.1:50367 Next Heartbeat in: 5 seconds. cancelled
 0 pending operation. old experation: 1805001 now expires at: 1810009 current ti
me: 1805009
finished processing this heartbeat for sending to target 127.0.0.1:50367

但现在我又陷入了困境。我觉得我需要以某种方式检查 m_timerHeartBeatSend 的内部结构才能更进一步。

【问题讨论】:

  • 哇。为什么这么复杂。 995 是什么?
  • 我不知道,它永远不会被击中。我继承了这个代码库,并试图将驱动 API Server 的一小部分变成正反面。
  • 我会考虑删除那个条件。第一个分支说“如果计时器没有被取消(即超时)”,第二个分支应该只处理 all 错误,否则可能会出现静默停止链的情况。当然,您也可以在发生这种情况时记录下来。
  • 等一下?你为什么不告诉 use m_timerHeartBeatSend 以前是什么?您现在应该考虑包含该代码 - 也许让它自包含。
  • 也许可以从这里开始:coliru.stacked-crooked.com/a/b2b7986d31081297 这是我在大约 20 分钟前试图理解它时创建的...

标签: c++ boost timer boost-asio


【解决方案1】:

原来问题出在为此计时器定义的 time_traits 结构中。它使用无符号数学,当减去的值大于另一个值时,它会把计时器搞砸。最终它会恢复。如果您在代码库中看到类似问题,请确保您的特征允许负值。

【讨论】:

  • 有趣。经验教训:在 SO! 上发布时在 SSCCE 中包含相关代码!问题会很明显。 (有时人们甚至spot it before posting
猜你喜欢
  • 1970-01-01
  • 2013-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
  • 2020-12-15
  • 1970-01-01
相关资源
最近更新 更多