summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2016-01-21 18:15:50 (GMT)
committerKevin Smith <git@kismith.co.uk>2016-01-21 18:24:25 (GMT)
commit8480bdda831e4d18c1979f40badb1bc985e78865 (patch)
tree10c68a327666fd7e352be3ce54865e50f77a161b
parentf377207cb896679b4eab9f6773d9d071700852ad (diff)
downloadswift-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.cpp14
-rw-r--r--Swiften/Network/BoostTimer.h1
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;
};
}