Ниже приведен пример кода Timer, который я использую на своем сервере. Это многопоточный процесс, который обрабатывает множество данных. После того, как таймер триггеров выполняет некоторые операции на обработанных данных и перезагрузится для нового временисброс boost :: deadline_timer в обработчике, вызывающем сбой
class MyTimer
{
public:
MyTimer(boost::asio::io_service& ios):strand_(ios)
{
for (int i = 0; i < 10; i++)
{
std::auto_ptr<boost::thread> thread(
new boost::thread(boost::bind(&boost::asio::io_service::run,
&ios_)));
thread_pool_.push_back(thread.get());
thread.release();
}
boost::posix_time::seconds expTime(10);
eodTimer_.reset(new boost::asio::deadline_timer(ios));
eodTimer_->expires_from_now(expTime);
eodTimer_->async_wait(boost::bind(&MyTimer::onTimer, this));
};
~MyTimer()
{
ThreadPool::iterator it(thread_pool_.begin());
for (; it != thread_pool_.end(); ++it)
{
(*it)->join();
delete *it;
}
}
void onTimer()
{
//do some stuff...
// reset timer
boost::posix_time::seconds expTime(10);
eodTimer_->expires_from_now(expTime);
eodTimer_->async_wait(boost::bind(&MyTimer::onTimer, this));
}
private:
boost::asio::io_service ios;
boost::asio::strand strand_;
boost::scoped_ptr<boost::asio::deadline_timer> eodTimer_;
};
До сих пор я не вижу никакой проблемы с этим кодом. Но после нескольких часов работы моего сервера происходит сбой. Stack trace указывает мне на :: обработчик обратного вызова onTimer.
#0 0x0a446c06 in boost::asio::detail::timer_queue<boost::asio::time_traits<boost::posix_time::ptime> >::cancel_timer (this=0xe3be0bc,
timer_token=0xe9877ec) at /vobs/FO_FOX/fo_fx_appl/appl/include/boost/asio/detail/timer_queue.hpp:141
#1 0x0a445791 in boost::asio::detail::epoll_reactor<false>::cancel_timer<boost::asio::time_traits<boost::posix_time::ptime> > (this=0xe49f498,
timer_queue=..., token=0xe9877ec) at /vobs/FO_FOX/fo_fx_appl/appl/include/boost/asio/detail/epoll_reactor.hpp:424
#2 0x0a444197 in boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime>, boost::asio::detail:: epoll_reactor<false> >::cancel (this=0xe3be0a8, impl=..., ec=...) at /vobs/FO_FOX/fo_fx_appl/appl/include/boost/asio/detail/deadline_timer_service.hpp:104 #3 0x0a443f31 in boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime>, boost::asio::detail:: epoll_reactor<false> >::expires_at (this=0xe3be0a8, impl=..., expiry_time=..., ec=...)
at /vobs/FO_FOX/fo_fx_appl/appl/include/boost/asio/detail/deadline_timer_service.hpp:120
#4 0x0a441e92 in boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime>, boost::asio::detail:: epoll_reactor<false> >::expires_from_now (this=0xe3be0a8, impl=..., expiry_time=..., ec=...)
at /vobs/FO_FOX/fo_fx_appl/appl/include/boost/asio/detail/deadline_timer_service.hpp:137
#5 0x0a43f895 in boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime> >:: expires_from_now (
this=0xe49f438, impl=..., expiry_time=..., ec=...) at /vobs/FO_FOX/fo_fx_appl/appl/include/boost/asio/deadline_timer_service.hpp: 144
#6 0x0a451d64 in 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::ptime, boost::asio::time_traits<boost::posix_time::ptime> > >::expires_from_now (this=0xe9877e8, expiry_time=...)
at /vobs/FO_FOX/fo_fx_appl/appl/include/boost/asio/basic_deadline_timer.hpp:297
#7 0x0a44e941 in fxpay::AggregatorRouter::Impl::MyTimer::onTimer (this=0xe987e48) at MyTimer.cpp:183
Есть ли что-то не так, как я использую boost :: dead_line timer? (Я использую версию ускорения 1,39)
Я использую strand для обработки некоторых других задач asio, которые выполняются на высокой частоте. Для упрощения я не скопировал код. В этом случае таймер истекает через 24 часа и снова сбрасывается на 24Hrs в обработчике. И есть только один объект таймера. Я не уверен, есть ли возможность гонки для таймера. Поправьте меня, если я ошибаюсь. – user1545583
Нет, если таймер не доступен ни из одной другой нити. В этом случае вы, вероятно, будете иметь гонку данных, когда _ «она выполняет некоторую операцию над обработанными данными» _. Но тогда мы не можем сказать, потому что соответствующего кода там нет. – sehe
Я забыл упомянуть ранее, что я должен был иметь. В вышеперечисленной трассировке стека, когда я проверяю количество элементов в boost :: asio :: detail :: timer_queue, я вижу число объектов в очереди как «92», что довольно странно, поскольку таймер сбрасывается через 24 часа и процесс выполняется в течение многих дней. Все объекты были повреждены. Кто-нибудь наблюдал такое поведение раньше? – user1545583