We’re seeing an issue with ManagedStaticMutex. There is a race condition between mutex_init_flag and the call_once usage in getManagedStaticMutex, at least on MSVC 2017.
The sequence of operations we see during startup are as follows:
- The first global ManagedStatic initializes, causing getManagedStaticMutex to call initializeMutex through std::call_once
- Some N number of additional global ManagedStatic initialize, where getManagedStaticMutex skips initializeMutex since it has already been called
- The global constructor for “mutex_init_flag” runs, resetting the flag indicating the call has already been made
- Another global ManagedStatic initializes, causing getManagedStaticMutex to be called, but this time initializeMutex is run since the mutex_init_flag flag was reset
After (4), the original ManagedStaticMutex is leaked. Additionally, (1) and (2) are operating on an uninitialized global variable.
As a fix, is there anything wrong with making mutex_init_flag function-local in getManagedStaticMutex? Its only use is in that function, and this would guarantee mutex_init_flag is initialized before use.