diff --git a/emper/lib/LinuxVersion.cpp b/emper/lib/LinuxVersion.cpp index 614407cefa2bbdbbedac4ebd23cbadd40f863b1b..4fb3c582d9e4a5ac97f041c249add63fc82294c6 100644 --- a/emper/lib/LinuxVersion.cpp +++ b/emper/lib/LinuxVersion.cpp @@ -1,11 +1,12 @@ // SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright © 2021 Florian Fischer +// Copyright © 2021-2022 Florian Fischer, Florian Schmaus #include "lib/LinuxVersion.hpp" #include <sys/utsname.h> #include <cerrno> #include <cstdlib> +#include <mutex> #include "Common.hpp" @@ -35,19 +36,30 @@ static auto checked_strtol(const std::string& s) -> long { namespace emper::lib { -std::string LinuxVersion::globalVersion; - -LinuxVersion::LinuxVersion() { - if (globalVersion.empty()) { - struct utsname buf; - if (uname(&buf)) { - DIE_MSG_ERRNO("Failed to invoke uname()"); +auto LinuxVersion::getUtsRelease() -> const std::string& { + // Use "construct (members) on first use idiom" to prevent the "static initialization order + // fiasco/problem". + static std::string utsRelease; + // This mutex will become necessary once we call getUtsRelease(), + // and by implication LinuxVersion's constructor, concurrently. So + // it can not hurt to have it right now. + static std::mutex utsReleaseMutex; + + { + const std::lock_guard<std::mutex> lock(utsReleaseMutex); + if (utsRelease.empty()) { + struct utsname buf; + if (uname(&buf)) { + DIE_MSG_ERRNO("Failed to invoke uname()"); + } + utsRelease = std::string(buf.release); } - globalVersion = std::string(buf.release); } - version = globalVersion; + return utsRelease; } +LinuxVersion::LinuxVersion() { version = getUtsRelease(); } + // Returns 1 if s is smaller, -1 if this is smaller, 0 if equal auto LinuxVersion::compare(const std::string& s) -> int { size_t dot_pos, dot_pos2; diff --git a/emper/lib/LinuxVersion.hpp b/emper/lib/LinuxVersion.hpp index 2d3b5713f6ce18743a26933c2817dcbe7f55b9d3..42eb611ebc0c797c7376f726d59c6cfe439a9bbb 100644 --- a/emper/lib/LinuxVersion.hpp +++ b/emper/lib/LinuxVersion.hpp @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright © 2021 Florian Fischer +// Copyright © 2021-2022 Florian Fischer, Florian Schmaus #pragma once #include <string> @@ -9,7 +9,7 @@ class TestLinuxVersion; namespace emper::lib { class LinuxVersion { friend class ::TestLinuxVersion; - static std::string globalVersion; + static auto getUtsRelease() -> const std::string&; std::string version; auto compare(const std::string& s) -> int;