From a9739d873b18a52871946681d4be8dd389f07134 Mon Sep 17 00:00:00 2001
From: Florian Fischer <florian.fl.fischer@fau.de>
Date: Mon, 14 Sep 2020 18:49:26 +0200
Subject: [PATCH] Make log() thread-safe by dropping the log level map

Concurrently using the CLOG_CONFIG map can result in a segmentation fault.

To prevent concurrent access to LOG_CONFIG a new constexpr getLevelFor
is introduces analogue to getTagFor.
---
 emper/Debug.hpp | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/emper/Debug.hpp b/emper/Debug.hpp
index a4d99c28..ff0cc2a4 100644
--- a/emper/Debug.hpp
+++ b/emper/Debug.hpp
@@ -3,7 +3,6 @@
 #pragma once
 
 #include <iostream>	 // IWYU pragma: keep
-#include <map>			 // for allocator, map
 #include <sstream>	 // IWYU pragma: keep
 #include <string>		 // for string, operator<<
 
@@ -77,16 +76,33 @@ enum LogLevel {
 
 void worker_log(const std::string& prefix, const std::string& message);
 
-static const std::map<LogSubsystem, LogLevel> LOG_CONFIG = {
-		{LogSubsystem::PS, ALL},		{LogSubsystem::F, ALL},					 {LogSubsystem::C, ALL},
-		{LogSubsystem::CM, ALL},		{LogSubsystem::DISP, ALL},			 {LogSubsystem::SCHED, ALL},
-		{LogSubsystem::RUNTI, ALL}, {LogSubsystem::U_B_MPSC_Q, ALL},
-};
-
 template <LogSubsystem logSubsystem>
 class Logger {
  private:
-	static constexpr auto getTagFor(LogSubsystem system) -> char const* {
+	static constexpr LogLevel getLevelFor(LogSubsystem system) {
+		switch (system) {
+			case LogSubsystem::PS:
+				return ALL;
+			case LogSubsystem::F:
+				return ALL;
+			case LogSubsystem::C:
+				return ALL;
+			case LogSubsystem::CM:
+				return ALL;
+			case LogSubsystem::DISP:
+				return ALL;
+			case LogSubsystem::SCHED:
+				return ALL;
+			case LogSubsystem::RUNTI:
+				return ALL;
+			case LogSubsystem::U_B_MPSC_Q:
+				return ALL;
+			default:
+				return ALL;
+		}
+	}
+
+	static constexpr char const* getTagFor(LogSubsystem system) {
 		switch (system) {
 			case LogSubsystem::PS:
 				return "PS   ";
@@ -125,7 +141,7 @@ class Logger {
 		// Do not log any debug messages if NDEBUG is defined.
 		if (level >= Debug) return;
 #endif
-		if (level > LOG_CONFIG.at(logSubsystem)) return;
+		if (level > getLevelFor(logSubsystem)) return;
 
 		std::string subSystemTag = getTagFor(logSubsystem);
 		;
-- 
GitLab