diff options
author | Kevin Smith <git@kismith.co.uk> | 2016-01-21 18:15:50 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2016-01-21 18:24:25 (GMT) |
commit | 8480bdda831e4d18c1979f40badb1bc985e78865 (patch) | |
tree | 10c68a327666fd7e352be3ce54865e50f77a161b | |
parent | f377207cb896679b4eab9f6773d9d071700852ad (diff) | |
download | swift-8480bdda831e4d18c1979f40badb1bc985e78865.zip swift-8480bdda831e4d18c1979f40badb1bc985e78865.tar.bz2 |
Ensure that BoostTimers can't fire after stop()
Code review makes me think that if the timer fires at the same time as
stop() is called, it would be possible for the clearing of events from
the loop to happen before the event is put into the loop, leading to
the sort of crashes we've seen with timers firing and access exceptions.
I can't reproduce those to know if this fixes them, and I'm not even sure
I'm not being dense thinking this patch fixes a real issue.
Test-Information:
Unit tests pass
Change-Id: I76337d5556a9c3902d5c2f4da754ae657810d436
-rw-r--r-- | Swiften/Network/BoostTimer.cpp | 14 | ||||
-rw-r--r-- | Swiften/Network/BoostTimer.h | 1 |
2 files changed, 12 insertions, 3 deletions
diff --git a/Swiften/Network/BoostTimer.cpp b/Swiften/Network/BoostTimer.cpp index 30f5180..c30fe32 100644 --- a/Swiften/Network/BoostTimer.cpp +++ b/Swiften/Network/BoostTimer.cpp @@ -15,7 +15,7 @@ namespace Swift { BoostTimer::BoostTimer(int milliseconds, boost::shared_ptr<boost::asio::io_service> service, EventLoop* eventLoop) : - timeout(milliseconds), ioService(service), eventLoop(eventLoop) { + timeout(milliseconds), ioService(service), eventLoop(eventLoop), shuttingDown(false) { timer.reset(new boost::asio::deadline_timer(*service)); } @@ -29,6 +29,7 @@ BoostTimer::~BoostTimer() { void BoostTimer::start() { { boost::mutex::scoped_lock lockTimer(timerMutex); + shuttingDown = false; timer->expires_from_now(boost::posix_time::milliseconds(timeout)); timer->async_wait(boost::bind(&BoostTimer::handleTimerTick, shared_from_this(), boost::asio::placeholders::error)); } @@ -37,9 +38,10 @@ void BoostTimer::start() { void BoostTimer::stop() { { boost::mutex::scoped_lock lockTimer(timerMutex); + shuttingDown = true; timer->cancel(); + eventLoop->removeEventsFromOwner(shared_from_this()); } - eventLoop->removeEventsFromOwner(shared_from_this()); } void BoostTimer::handleTimerTick(const boost::system::error_code& error) { @@ -47,7 +49,13 @@ void BoostTimer::handleTimerTick(const boost::system::error_code& error) { assert(error == boost::asio::error::operation_aborted); } else { - eventLoop->postEvent(boost::bind(boost::ref(onTick)), shared_from_this()); + { + boost::mutex::scoped_lock lockTimer(timerMutex); + if (shuttingDown) { + return; + } + eventLoop->postEvent(boost::bind(boost::ref(onTick)), shared_from_this()); + } } } diff --git a/Swiften/Network/BoostTimer.h b/Swiften/Network/BoostTimer.h index a246b75..3227031 100644 --- a/Swiften/Network/BoostTimer.h +++ b/Swiften/Network/BoostTimer.h @@ -43,5 +43,6 @@ namespace Swift { boost::scoped_ptr<boost::asio::deadline_timer> timer; boost::mutex timerMutex; EventLoop* eventLoop; + bool shuttingDown; }; } |