From 67b92faf0c03d5186014e346b4f607cedc3f47f2 Mon Sep 17 00:00:00 2001 From: "Alexander Kutsan (GitHub)" Date: Tue, 23 Jun 2020 00:57:06 +0300 Subject: Fixes race condition in messagemeter.h (#3377) SDLCORE-373 Unprotected critical section accessed by two different threads, timing_map was being modified by clearing the map identifiers causing a crash in boost::date_time Review: Change RWLock to Lock, Added FrequencyImpl private method Co-authored-by: Mario Godinez --- src/components/include/utils/messagemeter.h | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/components/include/utils/messagemeter.h b/src/components/include/utils/messagemeter.h index 1148a65b57..fb70839640 100644 --- a/src/components/include/utils/messagemeter.h +++ b/src/components/include/utils/messagemeter.h @@ -37,8 +37,11 @@ #include #include #include "utils/date_time.h" +#include "utils/lock.h" namespace utils { + +CREATE_LOGGERPTR_GLOBAL(logger_, "MessageMeter") /** @brief The MessageMeter class need to count message frequency Default time range value is 1 second @@ -86,10 +89,13 @@ class MessageMeter { date_time::TimeDuration time_range() const; private: + size_t FrequencyImpl(const Id& id); + date_time::TimeDuration time_range_; typedef std::multiset Timings; typedef std::map TimingMap; TimingMap timing_map_; + sync_primitives::Lock timing_map_lock_; }; template @@ -99,22 +105,33 @@ MessageMeter::MessageMeter() { template size_t MessageMeter::TrackMessage(const Id& id) { + LOG4CXX_AUTO_TRACE(logger_); return TrackMessages(id, 1); } template size_t MessageMeter::TrackMessages(const Id& id, const size_t count) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(timing_map_lock_); Timings& timings = timing_map_[id]; const date_time::TimeDuration current_time = date_time::getCurrentTime(); for (size_t i = 0; i < count; ++i) { // Adding to the end is amortized constant timings.insert(timings.end(), current_time); } - return Frequency(id); + return FrequencyImpl(id); } template size_t MessageMeter::Frequency(const Id& id) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(timing_map_lock_); + return FrequencyImpl(id); +} + +template +size_t MessageMeter::FrequencyImpl(const Id& id) { + LOG4CXX_AUTO_TRACE(logger_); typename TimingMap::iterator it = timing_map_.find(id); if (it == timing_map_.end()) { return 0u; @@ -131,21 +148,27 @@ size_t MessageMeter::Frequency(const Id& id) { template void MessageMeter::RemoveIdentifier(const Id& id) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(timing_map_lock_); timing_map_.erase(id); } template void MessageMeter::ClearIdentifiers() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(timing_map_lock_); timing_map_.clear(); } template void MessageMeter::set_time_range(const size_t time_range_msecs) { + LOG4CXX_AUTO_TRACE(logger_); time_range_ = date_time::milliseconds(time_range_msecs); } template void MessageMeter::set_time_range( const date_time::TimeDuration& time_range) { + LOG4CXX_AUTO_TRACE(logger_); time_range_ = time_range; } template -- cgit v1.2.1