Add missing concurrency protection in logger (#12325)

This commit is contained in:
paradust7 2022-05-23 13:50:25 -07:00 committed by GitHub
parent 0f9c78c3eb
commit 367a2d4b29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 4 deletions

@ -152,12 +152,14 @@ void Logger::addOutput(ILogOutput *out)
void Logger::addOutput(ILogOutput *out, LogLevel lev) void Logger::addOutput(ILogOutput *out, LogLevel lev)
{ {
MutexAutoLock lock(m_mutex);
m_outputs[lev].push_back(out); m_outputs[lev].push_back(out);
m_has_outputs[lev] = true; m_has_outputs[lev] = true;
} }
void Logger::addOutputMasked(ILogOutput *out, LogLevelMask mask) void Logger::addOutputMasked(ILogOutput *out, LogLevelMask mask)
{ {
MutexAutoLock lock(m_mutex);
for (size_t i = 0; i < LL_MAX; i++) { for (size_t i = 0; i < LL_MAX; i++) {
if (mask & LOGLEVEL_TO_MASKLEVEL(i)) { if (mask & LOGLEVEL_TO_MASKLEVEL(i)) {
m_outputs[i].push_back(out); m_outputs[i].push_back(out);
@ -168,6 +170,7 @@ void Logger::addOutputMasked(ILogOutput *out, LogLevelMask mask)
void Logger::addOutputMaxLevel(ILogOutput *out, LogLevel lev) void Logger::addOutputMaxLevel(ILogOutput *out, LogLevel lev)
{ {
MutexAutoLock lock(m_mutex);
assert(lev < LL_MAX); assert(lev < LL_MAX);
for (size_t i = 0; i <= lev; i++) { for (size_t i = 0; i <= lev; i++) {
m_outputs[i].push_back(out); m_outputs[i].push_back(out);
@ -177,6 +180,7 @@ void Logger::addOutputMaxLevel(ILogOutput *out, LogLevel lev)
LogLevelMask Logger::removeOutput(ILogOutput *out) LogLevelMask Logger::removeOutput(ILogOutput *out)
{ {
MutexAutoLock lock(m_mutex);
LogLevelMask ret_mask = 0; LogLevelMask ret_mask = 0;
for (size_t i = 0; i < LL_MAX; i++) { for (size_t i = 0; i < LL_MAX; i++) {
std::vector<ILogOutput *>::iterator it; std::vector<ILogOutput *>::iterator it;
@ -386,6 +390,6 @@ void LogOutputBuffer::logRaw(LogLevel lev, const std::string &line)
default: break; default: break;
} }
} }
MutexAutoLock lock(m_buffer_mutex);
m_buffer.push(color.append(line)); m_buffer.emplace(color.append(line));
} }

@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#if !defined(_WIN32) // POSIX #if !defined(_WIN32) // POSIX
#include <unistd.h> #include <unistd.h>
#endif #endif
#include "threading/mutex_auto_lock.h"
#include "util/basic_macros.h" #include "util/basic_macros.h"
#include "util/stream.h" #include "util/stream.h"
#include "irrlichttypes.h" #include "irrlichttypes.h"
@ -168,24 +169,31 @@ public:
void clear() void clear()
{ {
MutexAutoLock lock(m_buffer_mutex);
m_buffer = std::queue<std::string>(); m_buffer = std::queue<std::string>();
} }
bool empty() const bool empty() const
{ {
MutexAutoLock lock(m_buffer_mutex);
return m_buffer.empty(); return m_buffer.empty();
} }
std::string get() std::string get()
{ {
if (empty()) MutexAutoLock lock(m_buffer_mutex);
if (m_buffer.empty())
return ""; return "";
std::string s = m_buffer.front(); std::string s = std::move(m_buffer.front());
m_buffer.pop(); m_buffer.pop();
return s; return s;
} }
private: 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<std::string> m_buffer; std::queue<std::string> m_buffer;
Logger &m_logger; Logger &m_logger;
}; };