diff --git a/core/base/src/TDirectory.cxx b/core/base/src/TDirectory.cxx index b9aa5d9b91a0a637eb5dc3cb2202b735908a3547..393b1724163d8137c61ad6d9535daf0bb51b97bc 100644 --- a/core/base/src/TDirectory.cxx +++ b/core/base/src/TDirectory.cxx @@ -543,7 +543,10 @@ void TDirectory::Clear(Option_t *) //////////////////////////////////////////////////////////////////////////////// /// Delete all objects from memory and directory structure itself. - +/// if option is "slow", iterate through the containers in a way to can handle +/// 'external' modification (induced by recursions) +/// if option is "nodelete", write the TDirectory but do not delete the contained +/// objects. void TDirectory::Close(Option_t *option) { if (!fList) { @@ -553,26 +556,30 @@ void TDirectory::Close(Option_t *option) // Save the directory key list and header Save(); - Bool_t slow = option ? (!strcmp(option, "slow") ? kTRUE : kFALSE) : kFALSE; - if (!slow) { - // Check if it is wise to use the fast deletion path. - TObjLink *lnk = fList->FirstLink(); - while (lnk) { - if (lnk->GetObject()->IsA() == TDirectory::Class()) { - slow = kTRUE; - break; + Bool_t nodelete = option ? (!strcmp(option, "nodelete") ? kTRUE : kFALSE) : kFALSE; + + if (!nodelete) { + Bool_t slow = option ? (!strcmp(option, "slow") ? kTRUE : kFALSE) : kFALSE; + if (!slow) { + // Check if it is wise to use the fast deletion path. + TObjLink *lnk = fList->FirstLink(); + while (lnk) { + if (lnk->GetObject()->IsA() == TDirectory::Class()) { + slow = kTRUE; + break; + } + lnk = lnk->Next(); } - lnk = lnk->Next(); } - } - // Delete objects from directory list, this in turn, recursively closes all - // sub-directories (that were allocated on the heap) - // if this dir contains subdirs, we must use the slow option for Delete! - // we must avoid "slow" as much as possible, in particular Delete("slow") - // with a large number of objects (eg >10^5) would take for ever. - if (slow) fList->Delete("slow"); - else fList->Delete(); + // Delete objects from directory list, this in turn, recursively closes all + // sub-directories (that were allocated on the heap) + // if this dir contains subdirs, we must use the slow option for Delete! + // we must avoid "slow" as much as possible, in particular Delete("slow") + // with a large number of objects (eg >10^5) would take for ever. + if (slow) fList->Delete("slow"); + else fList->Delete(); + } CleanTargets(); } diff --git a/core/base/src/TROOT.cxx b/core/base/src/TROOT.cxx index 34401511878c6114911fd65a20f6f832cbc6c0db..63578f63ad9448d555a3f2271dd57b1026e44993 100644 --- a/core/base/src/TROOT.cxx +++ b/core/base/src/TROOT.cxx @@ -1089,7 +1089,8 @@ namespace { // is not seen as part of the list. // We will later, remove all the object (see files->Clear() cursor->SetObject(&harmless); // this must not be zero otherwise things go wrong. - dir->Close(); + // See related comment at the files->Clear("nodelete"); + dir->Close("nodelete"); // Put it back cursor->SetObject(dir); } diff --git a/core/meta/src/TClass.cxx b/core/meta/src/TClass.cxx index ae95138a9f9bc91f95a7658b4297bc45612a64b3..7b02c050f192d0dd761d28886041102aa0f6a411 100644 --- a/core/meta/src/TClass.cxx +++ b/core/meta/src/TClass.cxx @@ -2732,6 +2732,7 @@ Int_t TClass::GetBaseClassOffset(const TClass *toBase, void *address, bool isDer ClassInfo_t* derived = GetClassInfo(); ClassInfo_t* base = toBase->GetClassInfo(); if(derived && base) { + // TClingClassInfo::GetBaseOffset takes the lock. return gCling->ClassInfo_GetBaseOffset(derived, base, address, isDerivedObject); } else { diff --git a/io/io/src/TDirectoryFile.cxx b/io/io/src/TDirectoryFile.cxx index 627440ed38f0052416d26a48b06360f8bbf57915..7a7ecfc1a1c19fd4858e9554f1701e1597e204ea 100644 --- a/io/io/src/TDirectoryFile.cxx +++ b/io/io/src/TDirectoryFile.cxx @@ -532,7 +532,7 @@ TDirectory *TDirectoryFile::GetDirectory(const char *apath, //////////////////////////////////////////////////////////////////////////////// /// Delete all objects from memory and directory structure itself. -void TDirectoryFile::Close(Option_t *) +void TDirectoryFile::Close(Option_t *option) { if (!fList || !fSeekDir) { return; @@ -541,20 +541,24 @@ void TDirectoryFile::Close(Option_t *) // Save the directory key list and header Save(); - Bool_t fast = kTRUE; - TObjLink *lnk = fList->FirstLink(); - while (lnk) { - if (lnk->GetObject()->IsA() == TDirectoryFile::Class()) {fast = kFALSE;break;} - lnk = lnk->Next(); - } - // Delete objects from directory list, this in turn, recursively closes all - // sub-directories (that were allocated on the heap) - // if this dir contains subdirs, we must use the slow option for Delete! - // we must avoid "slow" as much as possible, in particular Delete("slow") - // with a large number of objects (eg >10^5) would take for ever. - { - if (fast) fList->Delete(); - else fList->Delete("slow"); + Bool_t nodelete = option ? (!strcmp(option, "nodelete") ? kTRUE : kFALSE) : kFALSE; + + if (!nodelete) { + Bool_t fast = kTRUE; + TObjLink *lnk = fList->FirstLink(); + while (lnk) { + if (lnk->GetObject()->IsA() == TDirectoryFile::Class()) {fast = kFALSE;break;} + lnk = lnk->Next(); + } + // Delete objects from directory list, this in turn, recursively closes all + // sub-directories (that were allocated on the heap) + // if this dir contains subdirs, we must use the slow option for Delete! + // we must avoid "slow" as much as possible, in particular Delete("slow") + // with a large number of objects (eg >10^5) would take for ever. + { + if (fast) fList->Delete(); + else fList->Delete("slow"); + } } // Delete keys from key list (but don't delete the list header) diff --git a/io/io/src/TFile.cxx b/io/io/src/TFile.cxx index 01730b99f6cc1e0f771794f4fb86b72c791905b0..52089f63979b931b23845ed6328962507ad0b0d6 100644 --- a/io/io/src/TFile.cxx +++ b/io/io/src/TFile.cxx @@ -546,6 +546,17 @@ TFile::~TFile() { Close(); + // In case where the TFile is still open at 'tear-down' time the order of operation will be + // call Close("nodelete") + // then later call delete TFile + // which means that at this point we might still have object held and those + // might requires a 'valid' TFile object in their desctructor (for example, + // TTree call's GetReadCache which expects a non-null fCacheReadMap). + // So delete the objects (if any) now. + + if (fList) + fList->Delete("slow"); + SafeDelete(fAsyncHandle); SafeDelete(fCacheRead); SafeDelete(fCacheReadMap);