File 0001-Fix-static-initialization-order-for-UserFormatRegist.patch of Package netgen
From 8ac2961d1ac7522c018fe05ce95ba39cc63cf75a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de>
Date: Thu, 19 Dec 2024 01:28:35 +0100
Subject: [PATCH] Fix static initialization order for UserFormatRegister map
A std::map is in an invalid state when just zero-initialized, and needs
to be initialized by its constructor. As this initilization may be done
after the first call to Register, a crash will typically happen.
To fix this wrap all accesses to the map with a Meyers Singleton. Also
remove the extra Array - most accesses are using the key, and the few
format list iterations all sort the result afterwards anyway.
---
libsrc/interface/writeuser.cpp | 31 +++++++++++++++++++++++++------
libsrc/interface/writeuser.hpp | 25 ++++++++-----------------
libsrc/meshing/python_mesh.cpp | 4 +++-
3 files changed, 36 insertions(+), 24 deletions(-)
diff --git a/libsrc/interface/writeuser.cpp b/libsrc/interface/writeuser.cpp
index 04f3780..68af173 100644
--- a/libsrc/interface/writeuser.cpp
+++ b/libsrc/interface/writeuser.cpp
@@ -16,19 +16,38 @@
namespace netgen
{
- extern MeshingParameters mparam;
+ std::map<std::string, UserFormatRegister::UserFormatEntry>& UserFormatRegister::getFormats()
+ {
+ static std::map<std::string, UserFormatRegister::UserFormatEntry> formats = {};
+ return formats;
+ }
- Array<UserFormatRegister::UserFormatEntry> UserFormatRegister::entries;
- std::map<string, int> UserFormatRegister::format_to_entry_index;
+ void UserFormatRegister::Register(UserFormatRegister::UserFormatEntry && entry)
+ {
+ getFormats()[entry.format] = std::move(entry);
+ }
+
+ const bool UserFormatRegister::HaveFormat(string format)
+ {
+ const auto formats = getFormats();
+ return formats.find(format) != formats.end();
+ }
+
+ const UserFormatRegister::UserFormatEntry & UserFormatRegister::Get(string format)
+ {
+ return getFormats()[format];
+ }
+
+ extern MeshingParameters mparam;
void RegisterUserFormats (NgArray<const char*> & names,
NgArray<const char*> & extensions)
{
- for (const auto & entry : UserFormatRegister::entries)
+ for (const auto & entry : UserFormatRegister::getFormats())
{
- names.Append (entry.format.c_str());
- extensions.Append (entry.extensions[0].c_str());
+ names.Append (entry.second.format.c_str());
+ extensions.Append (entry.second.extensions[0].c_str());
}
}
diff --git a/libsrc/interface/writeuser.hpp b/libsrc/interface/writeuser.hpp
index 1835707..961d1e4 100644
--- a/libsrc/interface/writeuser.hpp
+++ b/libsrc/interface/writeuser.hpp
@@ -32,32 +32,23 @@ struct UserFormatRegister {
optional<FRead> read;
optional<FWrite> write;
};
- DLL_HEADER static Array<UserFormatEntry> entries;
- DLL_HEADER static std::map<string, int> format_to_entry_index;
+ static void Register(UserFormatEntry && entry);
- static void Register(UserFormatEntry && entry) {
- format_to_entry_index[entry.format] = entries.Size();
- entries.Append( std::move(entry) );
- }
-
- static const bool HaveFormat(string format) {
- return format_to_entry_index.count(format) > 0;
- }
- static const UserFormatEntry & Get(string format) {
- return entries[format_to_entry_index[format]];
- }
+ static const bool HaveFormat(string format);
+ DLL_HEADER static const UserFormatEntry & Get(string format);
template<typename TFunc>
static void IterateFormats(TFunc func, bool need_read=false, bool need_write=false) {
Array<string> import_formats;
- for(const auto & e: entries)
- if((!need_read || e.read) && (!need_write || e.write))
- import_formats.Append(e.format);
+ for(const auto & e: getFormats())
+ if((!need_read || e.second.read) && (!need_write || e.second.write))
+ import_formats.Append(e.second.format);
QuickSort(import_formats);
for(auto format : import_formats)
- func(entries[format_to_entry_index[format]]);
+ func(Get(format));
}
+ DLL_HEADER static std::map<std::string, UserFormatEntry>& getFormats();
};
struct RegisterUserFormat {
diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp
index 3a652e0..bd774d8 100644
--- a/libsrc/meshing/python_mesh.cpp
+++ b/libsrc/meshing/python_mesh.cpp
@@ -660,7 +660,8 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
string export_docu = "Export mesh to other file format. Supported formats are:\n";
Array<string> export_formats;
- for(auto & e : UserFormatRegister::entries)
+ for(auto & kv : UserFormatRegister::getFormats()) {
+ const auto e = kv.second;
if(e.write) {
string s = '\t'+e.format+"\t("+e.extensions[0];
for(auto & ext : e.extensions.Range(1, e.extensions.Size()))
@@ -668,6 +669,7 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
s += ")\n";
export_formats.Append(s);
}
+ }
QuickSort(export_formats);
for(const auto & s : export_formats)
export_docu += s;
--
2.47.1