From 367a2d4b29a4865a8f2d5b9717786a8660f226bc Mon Sep 17 00:00:00 2001 From: paradust7 <102263465+paradust7@users.noreply.github.com> Date: Mon, 23 May 2022 13:50:25 -0700 Subject: [PATCH] Add missing concurrency protection in logger (#12325) --- src/log.cpp | 8 ++++++-- src/log.h | 12 ++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/log.cpp b/src/log.cpp index 51652fe0a..ef998f161 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -152,12 +152,14 @@ void Logger::addOutput(ILogOutput *out) void Logger::addOutput(ILogOutput *out, LogLevel lev) { + MutexAutoLock lock(m_mutex); m_outputs[lev].push_back(out); m_has_outputs[lev] = true; } void Logger::addOutputMasked(ILogOutput *out, LogLevelMask mask) { + MutexAutoLock lock(m_mutex); for (size_t i = 0; i < LL_MAX; i++) { if (mask & LOGLEVEL_TO_MASKLEVEL(i)) { m_outputs[i].push_back(out); @@ -168,6 +170,7 @@ void Logger::addOutputMasked(ILogOutput *out, LogLevelMask mask) void Logger::addOutputMaxLevel(ILogOutput *out, LogLevel lev) { + MutexAutoLock lock(m_mutex); assert(lev < LL_MAX); for (size_t i = 0; i <= lev; i++) { m_outputs[i].push_back(out); @@ -177,6 +180,7 @@ void Logger::addOutputMaxLevel(ILogOutput *out, LogLevel lev) LogLevelMask Logger::removeOutput(ILogOutput *out) { + MutexAutoLock lock(m_mutex); LogLevelMask ret_mask = 0; for (size_t i = 0; i < LL_MAX; i++) { std::vector::iterator it; @@ -386,6 +390,6 @@ void LogOutputBuffer::logRaw(LogLevel lev, const std::string &line) default: break; } } - - m_buffer.push(color.append(line)); + MutexAutoLock lock(m_buffer_mutex); + m_buffer.emplace(color.append(line)); } diff --git a/src/log.h b/src/log.h index 5c6ba7d64..0a84332e7 100644 --- a/src/log.h +++ b/src/log.h @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #if !defined(_WIN32) // POSIX #include #endif +#include "threading/mutex_auto_lock.h" #include "util/basic_macros.h" #include "util/stream.h" #include "irrlichttypes.h" @@ -168,24 +169,31 @@ public: void clear() { + MutexAutoLock lock(m_buffer_mutex); m_buffer = std::queue(); } bool empty() const { + MutexAutoLock lock(m_buffer_mutex); return m_buffer.empty(); } std::string get() { - if (empty()) + MutexAutoLock lock(m_buffer_mutex); + if (m_buffer.empty()) return ""; - std::string s = m_buffer.front(); + std::string s = std::move(m_buffer.front()); m_buffer.pop(); return s; } private: + // g_logger serializes calls to logRaw() with a mutex, but that + // doesn't prevent get() / clear() from being called on top of it. + // This mutex prevents that. + mutable std::mutex m_buffer_mutex; std::queue m_buffer; Logger &m_logger; };