Crash in cling caused by header parsing in library load?

Dear ROOTers,
I’m facing a very strange issue: I was testing ROOT version 6.20/00 (I am interested in the performances of the new compression introduced there) and I came stumbling on a very strange crash.

Essentially my executable is linked against the experiment software library and creates an object of type AMSChain (inherited from TChain). As soon as this happens the executable crashes

In file included from rootdict_s dictionary payload:118:
/storage/gpfs_ams/ams/users/vformato/AMS/include/../include/EcalKRec.h:39:2: error: redefinition of enumerator 'kElectron'
        kElectron,
        ^
/storage/gpfs_ams/ams/users/vformato/devel/root-6.20.00.install/include/TPDGCode.h:25:31: note: previous definition is here
   kSu1Bar=-3203,kSearches0=7,kElectron=11,kPositron=-11,kNuE=12,
                              ^
In file included from rootdict_s dictionary payload:118:
/storage/gpfs_ams/ams/users/vformato/AMS/include/../include/EcalKRec.h:40:2: error: redefinition of enumerator 'kProton'
        kProton,
        ^
/storage/gpfs_ams/ams/users/vformato/devel/root-6.20.00.install/include/TPDGCode.h:31:21: note: previous definition is here
   kA2_1320Plus=215,kProton=2212,kProtonBar=-2212,
                    ^
Error in <TInterpreter::AutoParse>: Error parsing payload code for class AMSChain with content:

So it looks like the interpreter is lazy-loading the class dictionary on the spot, parsing all the headers and then (rightfully?) complaining about a redefinition of an existing enum.

I can reproduce the same exact crash just by firing up the interpreter, loading the experiment library via gSystem->Load(...) and creating a default-constructed AMSChain object

root [0] gSystem->Load("lib/linuxx8664gcc6.20/libntuple_slc6_PG_dynamic.so");
root [1] AMSChain ch
// same exact crash happens

My questions to you are

  1. Why doesn’t this happen with ROOT 6.18/04? What changed in regard to dictionary header parsing?
  2. Assuming that the ROOT 6.18/04 shows the correct/intended behavior, what’s a possible fix for this issue? (meaning: is it really necessary to parse and interpret everything in a fully fledged compiled executable / library? I really would like this to behave as in all previous ROOT versions)

Cheers,
Valerio


ROOT Version: 6.20/00
Platform: CentOS 7
Compiler: gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)


Hi Valerio,

I hand this over to @Axel.

It appears that the ROOT header TPDGCode.h is now also parsed during your dictionary generation and it unfortunately has a conflict with your code :frowning:
One workaround to update EcalKRec.h to make the enum an ‘enum class’ (This will require change in the rest of your code :frowning: ).

Unfortunately I’m not sure it’s a viable solution, that codebase is required to be backwards compatible to ROOT 5 and c++03 :confused:
And by the looks of it the change you suggest requires to touch the code in a lot of places, handling ROOT6 vs ROOT5 code with ifdefs so on a first look it’s a no-go.

I’ll downgrade to 6.18/04 for the time being until I can understand better where the TPDGCode header is included (a small reproducer I’m attaching shows this crash when I try to load from the interpreter, but the executable runs just fine root6.20_crash_reproducer.tar.gz (2.0 KB))

It seems to me that the offending line in ROOT 6.20 is in the “${ROOTSYS}/include/module.modulemap” file:

module "EG" {
  // ...
  module "TPDGCode.h" { header "TPDGCode.h" export * }
  // ...
  link "libEG.so"
  export *
}

Maybe, you do not need to link against “libEG”.

ROOT 6.18 used PCH (instead of the new “C++ modules”) and there was the “${ROOTSYS}/lib/libEG.rootmap” file (instead of the new “${ROOTSYS}/lib/EG.pcm” file).

That’s a nice clue, is it possible it was different in 6.18/04?

And yes, unfortunately the experiment library links libEG so it carries it over. I’ll take a look at why libEg is used, though

Then the simplest adaptation is the following:

// File EcalKRec.h
enum  Something {
    ..., kAMSElectron,
    ...
    kAMSProton,
};

or the slightly more risky

// File EcalKRec.h
enum  Something {
    ..., 
#ifndef __CLING__
    kElectron,
#endif
    ...
#ifndef __CLING__
    kProton,
#endif
};

@Axel Adding to @pcanal notes … the proper adaptation is the following:

// File TPDGCode.h
#ifndef ROOT_TPDGCode
#define ROOT_TPDGCode
namespace ROOT {
  // ...
  typedef enum {/* ... */
    kElectron=11
    /* ... */}
  PDG_t;
  // ...
} // namespace ROOT
#endif //ROOT_TPDGCode

The only other file which would need to be “adapted” is: montecarlo/pythia6/src/TPythia6Decayer.cxx

Enclosing the ROOT enum in the main namespace would be an excellent solution but for now I’ll try to see if we can manage to fix this upstream in the experiment SW.

Thanks for the pointers!

Worst case scenario I just have to wait for 6.20/06 :smiley:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.