From b31faa1f86ec3609d9112e504994cc8150a64b5f Mon Sep 17 00:00:00 2001 From: Philippe Canal <pcanal@fnal.gov> Date: Tue, 18 Jun 2013 23:44:06 +0200 Subject: [PATCH] Fix ROOT-5284 which was due to a unusual setup (in TParallelCoord) leading to only partial cleanup. In some case, for example TParallelCoord, a list (the pad's list of primitives) will contain both the container and the containees (the TParallelCoorVar) but if the Clear is being called from the destructor of the container of this list, one of the first thing done will be the remove the container (the pad) for the list (of Primitives of the canvas) that was connecting it (indirectly) to the list of cleanups. So in Clear and Delete, we temporarily add each list and TObjArray to the cleanup list and remove it later. --- core/cont/src/TList.cxx | 23 +++++++++++++++++++++++ core/cont/src/TObjArray.cxx | 14 +++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/core/cont/src/TList.cxx b/core/cont/src/TList.cxx index 0089d2e29c3..344d61678d6 100644 --- a/core/cont/src/TList.cxx +++ b/core/cont/src/TList.cxx @@ -68,6 +68,7 @@ #include "TList.h" #include "TClass.h" +#include "TROOT.h" #include <string> namespace std {} using namespace std; @@ -351,6 +352,16 @@ void TList::Clear(Option_t *option) return; } + // In some case, for example TParallelCoord, a list (the pad's list of + // primitives) will contain both the container and the containees + // (the TParallelCoorVar) but if the Clear is being called from + // the destructor of the container of this list, one of the first + // thing done will be the remove the container (the pad) for the + // list (of Primitives of the canvas) that was connecting it + // (indirectly) to the list of cleanups. + // So let's temporarily add the current list and remove it later. + bool needRegister = fFirst && TROOT::Initialized() && !gROOT->GetListOfCleanups()->FindObject(this); + if (needRegister) gROOT->GetListOfCleanups()->Add(this); while (fFirst) { TObjLink *tlk = fFirst; fFirst = fFirst->Next(); @@ -365,6 +376,7 @@ void TList::Clear(Option_t *option) } delete tlk; } + if (needRegister) ROOT::GetROOT()->GetListOfCleanups()->Remove(this); fFirst = fLast = fCache = 0; fSize = 0; Changed(); @@ -385,6 +397,16 @@ void TList::Delete(Option_t *option) if (slow) { + // In some case, for example TParallelCoord, a list (the pad's list of + // primitives) will contain both the container and the containees + // (the TParallelCoorVar) but if the Clear is being called from + // the destructor of the container of this list, one of the first + // thing done will be the remove the container (the pad) for the + // list (of Primitives of the canvas) that was connecting it + // (indirectly) to the list of cleanups. + // So let's temporarily add the current list and remove it later. + bool needRegister = fFirst && TROOT::Initialized() && !gROOT->GetListOfCleanups()->FindObject(this); + if (needRegister) gROOT->GetListOfCleanups()->Add(this); while (fFirst) { TObjLink *tlk = fFirst; fFirst = fFirst->Next(); @@ -397,6 +419,7 @@ void TList::Delete(Option_t *option) delete tlk; } + if (needRegister) ROOT::GetROOT()->GetListOfCleanups()->Remove(this); fFirst = fLast = fCache = 0; fSize = 0; diff --git a/core/cont/src/TObjArray.cxx b/core/cont/src/TObjArray.cxx index 1a4d16495f2..0336f5970e2 100644 --- a/core/cont/src/TObjArray.cxx +++ b/core/cont/src/TObjArray.cxx @@ -330,11 +330,23 @@ void TObjArray::Delete(Option_t *) { // Remove all objects from the array AND delete all heap based objects. - for (Int_t i = 0; i < fSize; i++) + // In some case, for example TParallelCoord, a list (the pad's list of + // primitives) will contain both the container and the containees + // (the TParallelCoorVar) but if the Clear is being called from + // the destructor of the container of this list, one of the first + // thing done will be the remove the container (the pad) for the + // list (of Primitives of the canvas) that was connecting it + // (indirectly) to the list of cleanups. + // So let's temporarily add the current list and remove it later. + bool needRegister = fSize && TROOT::Initialized() && !gROOT->GetListOfCleanups()->FindObject(this); + if (needRegister) gROOT->GetListOfCleanups()->Add(this); + for (Int_t i = 0; i < fSize; i++) { if (fCont[i] && fCont[i]->IsOnHeap()) { TCollection::GarbageCollect(fCont[i]); fCont[i] = 0; } + } + if (needRegister) ROOT::GetROOT()->GetListOfCleanups()->Remove(this); Init(fSize, fLowerBound); } -- GitLab