From 933bf248337217f1fc8fc7d4637896be2e7f9b29 Mon Sep 17 00:00:00 2001 From: Christopher Jones Date: Thu, 2 Oct 2014 14:34:58 -0500 Subject: [PATCH 1/2] Call TROOT::GetGlobalFunction instead of GetListOfGlobalFunctions Since the global function list needs to be locked to be thread safe, the simplest way of avoiding having to take the locks outside of TROOT is to call GetGlobalFunction instead. --- core/base/src/TMacro.cxx | 2 +- core/base/src/TQObject.cxx | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/base/src/TMacro.cxx b/core/base/src/TMacro.cxx index f9167cf4ce3a0..23267553d7202 100644 --- a/core/base/src/TMacro.cxx +++ b/core/base/src/TMacro.cxx @@ -245,7 +245,7 @@ Long_t TMacro::Exec(const char *params, Int_t* error) // if macro has been executed, look for global function with name // of macro and re-execute this global function, if not found then // macro is unnamed macro, which we re-execute from file - if (gROOT->GetListOfGlobalFunctions(kTRUE)->FindObject(GetName())) { + if ( gROOT->GetGlobalFunction(GetName(), 0, kTRUE) ) { gROOT->SetExecutingMacro(kTRUE); TString exec = GetName(); TString p = params; diff --git a/core/base/src/TQObject.cxx b/core/base/src/TQObject.cxx index ea1a062c2143d..cfa64c1029331 100644 --- a/core/base/src/TQObject.cxx +++ b/core/base/src/TQObject.cxx @@ -338,8 +338,7 @@ Int_t TQObject::CheckConnectArgs(TQObject *sender, TFunction *slotMethod = 0; if (!receiver_class) { // case of slot_method is compiled/intrepreted function - slotMethod = (TFunction*)gROOT->GetListOfGlobalFunctions(kTRUE)-> - FindObject(slot_method); + slotMethod = gROOT->GetGlobalFunction(slot_method,0,kTRUE); } else { slotMethod = !slot_params ? GetMethodWithPrototype(receiver_class, From cc40a20f89c539263adfd35762a92c410f018b2b Mon Sep 17 00:00:00 2001 From: Christopher Jones Date: Thu, 2 Oct 2014 14:38:45 -0500 Subject: [PATCH 2/2] Lock access to gROOT->fGlobalFunctions The list of global functions must be protected from simultaneous writes/reads. --- core/base/src/TROOT.cxx | 18 +++++++++++------- core/meta/src/TCint.cxx | 14 ++++++++++++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/core/base/src/TROOT.cxx b/core/base/src/TROOT.cxx index 47375d41744d2..aef8b41e8430d 100644 --- a/core/base/src/TROOT.cxx +++ b/core/base/src/TROOT.cxx @@ -1167,12 +1167,14 @@ TFunction *TROOT::GetGlobalFunction(const char *function, const char *params, // of all currently defined global functions from CINT (more expensive). // The param string must be of the form: "3189,\"aap\",1.3". - if (!params) + if (!params) { + R__LOCKGUARD2(gROOTMutex); return (TFunction *)GetListOfGlobalFunctions(load)->FindObject(function); - else { + } else { if (!fInterpreter) Fatal("GetGlobalFunction", "fInterpreter not initialized"); + R__LOCKGUARD2(gROOTMutex); TFunction *f; TIter next(GetListOfGlobalFunctions(load)); @@ -1194,18 +1196,20 @@ TFunction *TROOT::GetGlobalFunctionWithPrototype(const char *function, // of all currently defined global functions from CINT (more expensive). // The proto string must be of the form: "int, char*, float". - if (!proto) + if (!proto) { + R__LOCKGUARD2(gROOTMutex); return (TFunction *)GetListOfGlobalFunctions(load)->FindObject(function); - else { + } else { if (!fInterpreter) Fatal("GetGlobalFunctionWithPrototype", "fInterpreter not initialized"); - TFunction *f; - TIter next(GetListOfGlobalFunctions(load)); - TString mangled = gInterpreter->GetMangledNameWithPrototype(0, function, proto); + R__LOCKGUARD2(gROOTMutex); + TFunction *f; + TIter next(GetListOfGlobalFunctions(load)); + while ((f = (TFunction *) next())) { if (mangled == f->GetMangledName()) return f; } diff --git a/core/meta/src/TCint.cxx b/core/meta/src/TCint.cxx index 6310a4bf89b8e..8f50b845b555a 100644 --- a/core/meta/src/TCint.cxx +++ b/core/meta/src/TCint.cxx @@ -839,13 +839,23 @@ void TCint::UpdateListOfGlobalFunctions() // Update the list of pointers to global functions. This function // is called by TROOT::GetListOfGlobalFunctions(). - if (!gROOT->fGlobalFunctions) { + bool globalFunctionsAvailable = false; + { + R__LOCKGUARD(gROOTMutex); + globalFunctionsAvailable = gROOT->fGlobalFunctions != 0; + } + if (!globalFunctionsAvailable) { // No global functions registered yet, trigger it: gROOT->GetListOfGlobalFunctions(); // We were already called by TROOT::GetListOfGlobalFunctions() return; } - + + //NOTE: At the moment gROOTMutex== gCINTMutex so we only need to lock one. + // In the future, if they are seperated, then the locks must be taken in + // the proper order. + // gROOTMutex is used to protect gROOT->fGlobalFunctions + //R__LOCKGUARD2(gROOTMutex); R__LOCKGUARD2(gCINTMutex); G__MethodInfo t, *a;