C++ segfault using TTree::MergeTrees

I have a simple function to merge some trees given a list of filenames. The whole function just does

def mergeOther(listOfTrees,treeName):
    outFileName = getOutputFileName(listOfTrees[0])
        
    collection = ROOT.TList()
    for elem in listOfTrees:
        tfile = ROOT.TFile(elem,'read')
        ttree = tfile.Get(treeName)
        collection.Add(ttree)
    
    outputFile = ROOT.TFile(outFileName,'recreate')
    outputFile.cd()
    outputTree = ROOT.TTree.MergeTrees(collection)
    outputTree.Write()
    outputFile.Close()

When I execute this function I get occasional, non-reproducible segmentation violations:

 *** Break *** segmentation violation
Traceback (most recent call last):
  File "/u/kocolosk/afsdir/scripts/mergeTrees.py", line 150, in ?
    sys.exit(main())
  File "/u/kocolosk/afsdir/scripts/mergeTrees.py", line 141, in main
    [mergeOther(li,'chargedPionTree') for li in listsOfFiles if len(li) > 1]
  File "/u/kocolosk/afsdir/scripts/mergeTrees.py", line 97, in mergeOther
    outputTree = ROOT.TTree.MergeTrees(collection)
SystemError: problem in C++; program state has been reset

The input trees seem valid, and the segfault occurs on different sets of input trees each time I run the macro. Is there a way for me to debug what’s going on underneath? The full script is at

/afs/rhic.bnl.gov/star/users/kocolosk/public/scripts/mergeTrees.py

Incidentally, the following code does what I need, so the segfault in MergeTrees is not a showstopper on my end. Still curious about what wrong, but I assume at this point that it’s not a PyROOT problem.

def mergeOther(listOfTrees,treeName):
    outFileName = getOutputFileName(listOfTrees[0])
    
    firstFile = ROOT.TFile(listOfTrees[0],'read')
    firstTree = firstFile.Get(treeName)
    firstTree.SetBranchStatus('*',1)
    
    outFile = ROOT.TFile(outFileName,'recreate')
    outTree = firstTree.CloneTree()
    
    for elem in listOfTrees[1:]:
        tfile = ROOT.TFile(elem,'read')
        ttree = tfile.Get(treeName)
        ttree.SetBranchStatus('*',1)
        outTree.CopyEntries(ttree)
    
    outFile.cd()
    outTree.Write()
    outFile.Close()
    print 'merged file %s' % (outFileName,)

Hi,

it’s likely a problem here:for elem in listOfTrees: tfile = ROOT.TFile(elem,'read')The ‘tfile’ reference is being reused, so in every iteration, the dtor is called on the ROOT.TFile opened in the previous iteration of the loop. The dtor closes the file and erases the tree from memory. By using CloneTree, you keep a copy in memory, and hence no pb. The alternative is to keep all the files open (e.g. by appending the tfile to a (python) list object), untill your done with them.

Cheers,
Wim

Ah, of course … I can’t just toss the files on the heap in Python! Your suggestion works nicely. Thanks for taking a look.

Also, thanks for all your work developing and supporting PyROOT; it’s an impressive combination. Regards,

Adam