From cbfd8e4405e2892f414ce01e612d688c33a58715 Mon Sep 17 00:00:00 2001 From: Philippe Canal Date: Mon, 25 Jan 2021 13:44:57 -0600 Subject: [PATCH] Fix #7093: race condition tripping TEnum::GetEnum --- core/meta/src/TEnum.cxx | 8 +++++--- core/metacling/src/TCling.cxx | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/core/meta/src/TEnum.cxx b/core/meta/src/TEnum.cxx index 25a588e931c61..a3798271faebb 100644 --- a/core/meta/src/TEnum.cxx +++ b/core/meta/src/TEnum.cxx @@ -195,9 +195,7 @@ TEnum *TEnum::GetEnum(const char *enumName, ESearchAction sa) return en; } - // Lock need for gROOT->GetListOfClasses() and the later update/modification to - // the autoparsing state. - R__LOCKGUARD(gInterpreterMutex); + if (auto tClassScope = static_cast(gROOT->GetListOfClasses()->FindObject(scopeName))) { // If this is a class, load only if the user allowed interpreter lookup // If this is a namespace and the user did not allow for interpreter lookup, load but before disable @@ -236,6 +234,10 @@ TEnum *TEnum::GetEnum(const char *enumName, ESearchAction sa) return nullptr; } + // Keep the state consistent. I particular prevent change in the state of AutoLoading and AutoParsing allowance + // and gROOT->GetListOfClasses() and the later update/modification to the autoparsing state. + R__READ_LOCKGUARD(ROOT::gCoreMutex); + if (lastPos != enumName) { // We have a scope // All of this C gymnastic is to avoid allocations on the heap (see TClingLookupHelper__ExistingTypeCheck) diff --git a/core/metacling/src/TCling.cxx b/core/metacling/src/TCling.cxx index a5a60e681e375..c7fd3c78707da 100644 --- a/core/metacling/src/TCling.cxx +++ b/core/metacling/src/TCling.cxx @@ -6028,6 +6028,9 @@ Int_t TCling::DeepAutoLoadImpl(const char *cls) Int_t TCling::AutoLoad(const char *cls, Bool_t knowDictNotLoaded /* = kFALSE */) { + // Prevent update to IsClassAutoloading between our check and our actions. + R__READ_LOCKGUARD(ROOT::gCoreMutex); + // TClass::GetClass explicitly calls gInterpreter->AutoLoad. When called from // rootcling (in *_rdict.pcm file generation) it is a no op. // FIXME: We should avoid calling autoload when we know we are not supposed @@ -6042,7 +6045,7 @@ Int_t TCling::AutoLoad(const char *cls, Bool_t knowDictNotLoaded /* = kFALSE */) assert(IsClassAutoLoadingEnabled() && "Calling when AutoLoading is off!"); - R__LOCKGUARD(gInterpreterMutex); + R__WRITE_LOCKGUARD(ROOT::gCoreMutex); if (!knowDictNotLoaded && gClassTable->GetDictNorm(cls)) { // The library is already loaded as the class's dictionary is known.