Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Eliminate a "C++ initialization order fiasco" for geometryregister #125

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

xiphmont
Copy link

Current initialization of the global geometryregister suffers from a
classic 'initialization order fiasco'. Depending on the order the
compilation units are loaded/linked, the initialization of the global
GeometryRegisterArray is not guaranteed to happen (and indeed often
does not happen) before it is used. This leads to entries being
appended before it's initialized (usually 'succeeding', but potentially
causing memory corruption if the segment at that point isn't zeroed),
initialization then happening halfway through (wiping the initial
entries) and then the last entries being the only ones that show up.

The net effect is either a crash at startup, or several geometry types
seeming to be missing. Eg, step files will oad, but STL files are
just ignored. The bug is actively observed on, eg, Linux.

This patch implements a simple 'initialize at first access' convention
for the array, eliminating the ordering problem.

I've not reviewed the rest of the source for other potential examples
of the fiasco pattern; this fixes only the global geometryregister, since
that was actively biting.

Current initialization of the global geometryregister suffers from a
classic 'initialization order fiasco'.  Depending on the order the
compilation units are loaded/linked, the initialization of the global
geometryregisterarray is not guaranteed to happen (and indeed often
does not happen) before it is used.  This leads to entries being
appended before it's initialized (usually 'suceeding, but potentially
causing memory corruption if the segment at that point isn't zeroed),
initialization then happening halfway through (wiping the initial
entries) and then the last entries being the only ones that show up.

The net effect is either a crash at startup, or several geometry types
seeming to be missing.  Eg, step files will oad, but STL files are
just ignored.  The bug is actively observed on, eg, Linux.

This patch implements a simple 'initialize at first access' convention
for the array, eliminating the ordering problem.

I've not reviewed the rest of the source for other potential examples
of the fiasco pattern; this fixes only the geometryregister, since
that was actively biting.
libsrc/meshing/basegeom.cpp Show resolved Hide resolved
}

virtual shared_ptr<NetgenGeometry> LoadFromMeshFile (istream & ist) const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoadFromMeshFile is not reimplemented, but delegated to the registered GeometryRegister::LoadFromMeshFile.

Suggested change
virtual shared_ptr<NetgenGeometry> LoadFromMeshFile (istream & ist) const;
shared_ptr<NetgenGeometry> LoadFromMeshFile (istream & ist) const;

Comment on lines 339 to 340
public:
virtual ~GeometryRegisterArray()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid accidental misuse (copying) of the singleton.
Make non-virtual, singleton should never be reimplemented.

Suggested change
public:
virtual ~GeometryRegisterArray()
public:
GeometryRegisterArray(const GeometryRegisterArray &) = delete;
GeometryRegisterArray & operator=(const GeometryRegisterArray &) = delete;
private:
GeometryRegisterArray() = default;
~GeometryRegisterArray() = default;

@StefanBruens
Copy link
Contributor

This pattern is known as Meyers Singleton (after the C++ guru Scott Meyers). For a small overview of thread-safe singleton implementations, see https://www.modernescpp.com/index.php/thread-safe-initialization-of-a-singleton. Bottom line:

The Meyers Singleton is the easiest to get and the fastest one.

Comment on lines +36 to +39
if(stlgeometry){ // don't let the default initializer crash init
stlgeometry->SetSelectTrig(selecttrig);
stlgeometry->SetNodeOfSelTrig(nodeofseltrig);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is unrelated, and incorrect/insufficient (dito below).

stlgeometry is a private member of VisualSceneSTLMeshing, and it must be a nullptr here. (It unfortunately lacks an initializer, and thus may point to arbitrary memory). stlgeometry can only be set with SetGeometry().

See #128

@xiphmont xiphmont changed the title Eliminate a "C++ initialization order fiasco" for geometryregister WIP: Eliminate a "C++ initialization order fiasco" for geometryregister Jul 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants