在 boost::asio::io_service 上调用 run 时崩溃
Posted
技术标签:
【中文标题】在 boost::asio::io_service 上调用 run 时崩溃【英文标题】:Crash when calling run on boost::asio::io_service 【发布时间】:2014-05-28 02:50:06 【问题描述】:我正在尝试编写一个相对简单的类“CallbackTimer”,它需要一定的时间和一个函数,并且在经过一段时间后调用该函数。如有必要,可以重复几次。
这一切都按预期工作,但是当我在计时器完成之前调用 start 几次时偶尔会崩溃,但我看不出问题出在哪里。我认为这是因为我没有正确混合我的线程和 io_service,但我不确定。任何帮助或指示将不胜感激。
类如下
CallbackTimer::CallbackTimer(const std::function<void()>& callback) :
callback_(callback),
currentRepeats_(0),
//io_(boost::asio::io_service()),
timer_(new boost::asio::deadline_timer(io_)),
strand_(io_),
thread_(nullptr)
CallbackTimer::~CallbackTimer()
cancel();
void CallbackTimer::start(size_t intervalMillis, int repeats)
if (thread_)
cancel();
requestedRepeats_ = repeats;
intervalMillis_ = intervalMillis;
currentRepeats_ = 0;
runTimer();
thread_.reset(new std::thread([this]()
this->io_.run();
));
thread_->detach();
void CallbackTimer::cancel()
timer_->cancel();
if (thread_ && thread_->joinable())
thread_->join();
io_.reset();
void CallbackTimer::runCallback(const boost::system::error_code& e)
if (e == boost::asio::error::operation_aborted)
io_.stop();
return;
currentRepeats_++;
callback_();
if (currentRepeats_ >= requestedRepeats_)
io_.stop();
return;
runTimer();
void CallbackTimer::runTimer()
timer_->expires_from_now(boost::posix_time::millisec(intervalMillis_));
timer_->async_wait(strand_.wrap(std::bind(&CallbackTimer::runCallback, this, std::placeholders::_1)));
【问题讨论】:
【参考方案1】:一目了然,有两个潜在的问题:
CallbackTimer
类无法保证io_service::reset()
在未完成对run()
、run_one()
、poll()
或poll_one()
的调用时不被调用的前提条件,导致未指定的行为.
CallbackTimer::runCallback()
可以在 CallbackTimer
实例的生命周期结束后调用,从而调用未定义的行为。
这两个问题都是由于与运行io_service
的线程没有同步造成的。线程在CallbackTimer::start()
中创建后被分离,CallbackTimer::cancel()
中的 if 语句将始终为 false,导致不发生同步。这允许以下情况:
io_service::reset()
在thread_
在io_service::run()
内时被调用。
拥有io_service
的CallbackTimer
被释放,而thread_
在io_service::run()
内。
要解决此问题,请考虑不再与 thread_
分离,以便可能发生同步。
为了进一步调试,堆栈跟踪或mcve 可以帮助确定崩溃的确切来源。
【讨论】:
你是对的,删除 detach 调用停止了崩溃。以上是关于在 boost::asio::io_service 上调用 run 时崩溃的主要内容,如果未能解决你的问题,请参考以下文章
在 boost::asio::io_service 上调用 run 时崩溃
从作为分离线程运行的 boost::asio::io_service::work 捕获异常
C++ boost::asio::io_service创建线程池thread_group简单实例