2

deadline_timer::async_waitメソッドを呼び出すと、時々 segfault がスローされSendMessageAgainます。2 つの方法のいずれかで発生する可能性があります。以下にバックトレースを含めました。それはランダムに見えるので、どういうわけか競合状態が関係していると思います。io_serviceオブジェクトを持つクラスと、ioServiceそれぞれにタイマーがフックされている複数のスレッドがありますioServiceioService呼び出す前にロックする必要がありasync_waitますか? 私はそれがそれを処理したと思った。

おそらく、タイマーが作動したときにコードが中断されるのと関係があるのでしょう。他のコードも実行しているときに期限タイマーを設定する適切な方法は何ですか?

私が使用するコードSendMessageAgain

void Node::SendMessageAgain(unsigned long seqNum) {
  // figure out if and what to send (using object fields)
  if (should_send_again) {
    Send(...);
    timer->expires_from_now(INTERVAL);
    timer->async_wait(bind(&Node::SendMessageAgain, this, seqNum));
  }
}
#0 0x08060609 in boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> >::async_wait<boost::_bi::bind_t<void, boost::_mfi ::mf1<void, Node, unsigned long>, boost::_bi::list2<boost::_bi::value<Node*>, boost::_bi::value<unsigned long> > > > (this=0x14 , impl=..., ハンドラ=...)
    /usr/include/boost/asio/detail/deadline_timer_service.hpp:170 で
#1 boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime> >::async_wait<boost::_bi::bind_t<void で 0x0805e2e7 , boost::_mfi::mf1<void, Node, unsigned long>, boost::_bi::list2<boost::_bi::value<Node*>, boost::_bi::value<unsigned long> > > > (this=0x0, impl=...,
    handler=...) /usr/include/boost/asio/deadline_timer_service.hpp:135 で
#2 boost::asio::basic_deadline_timer<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime>, boost::asio::deadline_timer_service<boost::posix_time: で 0x0805bcbb :ptime, boost::asio::time_traits<boost::posix_time::ptime> > >::async_wait<boost::_bi::bind_t<void, boost::_mfi::mf1<void, Node, unsigned long> , boost::_bi::list2<boost::_bi::value<Node*>, boost::_bi::value<unsigned long> > > > (this=0x807fc50, handler=...)
    /usr/include/boost/asio/basic_deadline_timer.hpp:435 で
#3 Node::SendMessageAgain の 0x080555a2 (this=0xbfffefdc, seqNum=8)
    node.cpp:147 で
#0 __pthread_mutex_lock (mutex=0x2f200c4) at pthread_mutex_lock.c:50
#1 boost::asio::detail::posix_mutex::lock の 0x08056c79 (this=0x2f200c4)
    /usr/include/boost/asio/detail/posix_mutex.hpp:52 で
#2 boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex>::scoped_lock の 0x0805a036 (this=0xbfffeb04, m=...)
    /usr/include/boost/asio/detail/scoped_lock.hpp:36 で
#3 boost::asio::detail::epoll_reactor::schedule_timer<boost::asio::time_traits<boost::posix_time::ptime> の 0x08061dd0 > (this=0x2f200ac, queue=...,
    time=..., timer=..., op=0x807fca0)
    /usr/include/boost/asio/detail/impl/epoll_reactor.hpp:43 で
#4 boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> >::async_wait<boost::_bi::bind_t<void, boost::_mfi の 0x0806063a ::mf1<void, Node, unsigned long>, boost::_bi::list2<boost::_bi::value<Node*>, boost::_bi::value<unsigned long> > > > (this=0xb6b005fc 、impl=...、
    ハンドラ=...)
    /usr/include/boost/asio/detail/deadline_timer_service.hpp:170 で
#5 boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime> >::async_wait<boost::_bi::bind_t<void で 0x0805e2fd , boost::_mfi::mf1<void, Node, unsigned long>, boost::_bi::list2<boost::_bi::value<Node*>, boost::_bi::value<unsigned long> > > > (this=0xb6b005e8,
    impl=..., ハンドラ=...)
    /usr/include/boost/asio/deadline_timer_service.hpp:135 で
#6 0x0805bcd1 in boost::asio::basic_deadline_timer<boost::posix_time::ptime, bo---<return> を入力して続行するか、q <return> を入力して終了します---
ost::asio::time_traits<boost::posix_time::ptime>, boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime> > >::async_wait<boost::_bi::bind_t<void, boost::_mfi::mf1<void, Node, unsigned long>, boost::_bi::list2<boost::_bi::value<Node*> , boost::_bi::value<unsigned long> > > > (this=0xb6b005a0, handler=...)
    /usr/include/boost/asio/basic_deadline_timer.hpp:435 で
#7 Node::SendMessageAgain の 0x080555a7 (this=0xbfffefdc, seqNum=9)
    node.cpp:148 で
4

2 に答える 2

3

よし、直った。サムが示唆したように、それはオブジェクトの有効期間の問題でしたが、Node. が所有するオブジェクトにタイマーがありましたNode。コードに競合状態があり、クリティカル セクションの外でタイマーをリセットしていて、その所有者がクリティカル セクションの終了とタイマーのリセットの間に破棄されていました。クリティカルセクションを拡張しただけで修正されました。

async_waitコールバック (および関連付けられたポインター)がまだ存在してthisいた に属していたため、セグメンテーション違反がこれほどまでに明らかになった理由はわかりません。Node

于 2013-04-16T04:18:57.017 に答える
0

悪い:

timer->async_wait(bind(&Node::SendMessageAgain, this, seqNum, _1));

良い:

timer->async_wait(bind(&Node::SendMessageAgain, shared_from_this(), seqNum, _1));

Node に enable_shared_from_this を拡張させる

class Node : public boost::enable_shared_from_this<Node>

コールバックがまだスケジュールされている間にノードが破棄されたことが原因である場合、これで問題が解決する可能性があります。

于 2013-04-16T00:17:39.290 に答える