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