Problem 2230

Summary: Visual Studio Debug multithreaded build crashes in G4LossTableBuilder constructor
Product: Geant4 Reporter: Sergio Losilla <sergio.losilla>
Component: processes/electromagneticAssignee: Vladimir.Ivantchenko
Status: RESOLVED FIXED    
Severity: normal CC: daren.sawkey
Priority: P4    
Version: 10.6   
Hardware: All   
OS: Windows   

Description Sergio Losilla 2020-02-19 08:39:05 CET
On G4LossTableBuilder.cc line 97, non-master threads attempt to unlock a mutex that was never locked, which is undefined behavior and causes this type of build to crash.

The Geant4 version tested was 10.6.1, with Visual Studio 16.4.5.

The affected code looks like this:

G4LossTableBuilder::G4LossTableBuilder(G4bool master) : isMaster(master) 
{
  theParameters = G4EmParameters::Instance();
  splineFlag = true;
  isInitialized = false;
  if(isMaster || !theFlag) {
#ifdef G4MULTITHREADED
    G4MUTEXLOCK(&ltbMutex);
    if(isMaster || !theFlag) {
#endif
      isMaster = true;
      theDensityFactor = new std::vector<G4double>;
      theDensityIdx = new std::vector<G4int>;
      theFlag = new std::vector<G4bool>;
    } else {
      isMaster = false; <--- This line is never hit in multithreaded builds
    }
#ifdef G4MULTITHREADED
  }
  G4MUTEXUNLOCK(&ltbMutex); <---- CRASH
#endif
}

I am not quite sure what is supposed to happen, but if G4MULTITHREADED is defined the code can be simplified to this:

G4LossTableBuilder::G4LossTableBuilder(G4bool master) : isMaster(master) 
{
  theParameters = G4EmParameters::Instance();
  splineFlag = true;
  isInitialized = false;
  if(isMaster || !theFlag) {
    G4MUTEXLOCK(&ltbMutex);
    isMaster = true;
    theDensityFactor = new std::vector<G4double>;
    theDensityIdx = new std::vector<G4int>;
    theFlag = new std::vector<G4bool>;
  }
  G4MUTEXUNLOCK(&ltbMutex);
}

So if isMaster is false, this will result in undefined behavior. Also, note that the line "isMaster = false" is never hit for multithreaded builds.
Comment 1 Vladimir.Ivantchenko 2020-05-01 13:42:04 CEST
Hello,

thank you very much for this post. The bug is fixed, included in the Geant4 development version, and will be available with the public release.

VI