Crash on exit with THStack Draw() and GetHists()

Hello,

I’m getting a seg fault when exiting python when I use BOTH Draw() and GetHists() of THStack. I do not get the seg fault when using one or the other of the THStack methods.

Here is a code snippet using ROOT v5.26.00 with Python v2.5.4. that will seg fault when python attempts to exit. If I comment out either “st.Draw()” or “hlist = st.GetHists()” I don’t get a seg fault. How do these two methods interact with each other behind the scenes???

from ROOT import TH1F, THStack

h1 = TH1F('h1','hist 1',10,0,10)
h1.FillRandom("gaus",1000)
h2 = TH1F('h2','hist 2',10,0,10)
h2.FillRandom('gaus',1000)

st = THStack('st','stack')
st.Add(h1)
st.Add(h2)

#like this it will crash on exit
#comment out either of the following two lines and it will not crash on exit
st.Draw()
hlist = st.GetHists()

Any help would be greatly appreciated!

Thanks,
Andrew

Andrew,

the problem is that the TCanvas takes ownership of ‘st’ after it is drawn, this happens behind the scenes, so the binding things that st is still owned by python. Easiest solution is to:

from ROOT import SetOwnership SetOwnership(st, False)
Cheers,
Wim

Thanks Wim, that works.

A question for my own enlightenment, why does ROOT need to treat a THStack differently from a TH1 with respect to ownership and the canvas? If I do this same exercise (draw then access the object) with just a TH1, I don’t get a crash (which implies to me that the ownership of the TH1 is not transferred to the canvas when it is drawn). For example, this does not crash on exit:

from ROOT import TH1F
h1 = TH1F('h1','hist 1',10,0,10)
h1.FillRandom("gaus",1000)
h1.Draw()
title = h1.GetTitle()

Thank-you again for your solution and you time!

Cheers,
Andrew

Andrew,

looking at it in more detail … The real problem, and difference between TH1 and THStack is in the GetHists(). What happens is that this returns an internal data member of the THStack, and PyROOT sets its kMustCleanup bit to make sure that python gets notified when the list goes away. Problem is that the THStack deletes the list in its dtor, upon which the list object calls a RecursiveRemove, which goes back to the THStack. The latter checks its fHists variable in RecursiveRemove for non-NULL, but of course the variable is only set to NULL after the deletion is complete. Iow., RecursiveRemove proceeds and operates on a partially destroyed fHists, with a crash as result.

This could be fixed in ~THStack, I guess (by copying fHists into a temporary variable, then setting it to NULL before calling delete on the temporary), but “del hlist” should do the trick as well.

Cheers,
Wim

Thanks! Rather than mucking with THStack I will stick with your “del hlist” solution.

Thanks again,
Andrew