Segfault on reading TObjArray from tree

I have a root file containing a TTree, of which several branches are TObjArrays containing TH1Ds. When I try to access this from CINT, it works exactly as expected and I can extract and draw the histograms. However, when I try to access it from PyROOT, I get a segfault.

Here’s an example of an interpreter session trying to read the data:

In [1]: _file0 = ROOT.TFile("toy_with_data-run_0-expts_0_0.root")

In [2]: tr = _file0.Get("fitnt")                                                   

In [3]: for b in tr.GetListOfBranches():                 
    b.Print()
   ...:     
*Br    0 :best_fit_params : FitParamList                              *
*Entries :        1 : Total  Size=       7302 bytes  File Size  =       3567 *
*Baskets :        1 : Basket Size=    1280000 bytes  Compression=   1.90     *
*............................................................................*
*Br    1 :best_fit_params_fit1 : FitParamList                         *
*Entries :        1 : Total  Size=       7327 bytes  File Size  =       3572 *
*Baskets :        1 : Basket Size=    1280000 bytes  Compression=   1.90     *
*............................................................................*
*Br    2 :best_fit_params_fit2 : FitParamList                         *
*Entries :        1 : Total  Size=       7327 bytes  File Size  =       3665 *
*Baskets :        1 : Basket Size=    1280000 bytes  Compression=   1.85     *
*............................................................................*
*Br    3 :data      : TObjArray                                              *
*Entries :        1 : Total  Size=       4145 bytes  File Size  =        877 *
*Baskets :        1 : Basket Size=    1280000 bytes  Compression=   4.19     *
*............................................................................*
*Br    4 :best_fit_pdf : TObjArray                                           *
*Entries :        1 : Total  Size=     106927 bytes  File Size  =      27829 *
*Baskets :        1 : Basket Size=    1280000 bytes  Compression=   3.82     *
*............................................................................*
*Br    5 :best_fit_pdf_fit1 : TObjArray                                      *
*Entries :        1 : Total  Size=     106947 bytes  File Size  =      27838 *
*Baskets :        1 : Basket Size=    1280000 bytes  Compression=   3.82     *
*............................................................................*
*Br    6 :best_fit_pdf_fit2 : TObjArray                                      *
*Entries :        1 : Total  Size=     106947 bytes  File Size  =      27830 *
*Baskets :        1 : Basket Size=    1280000 bytes  Compression=   3.82     *
*............................................................................*

In [4]: tr.GetEntries()
Out[4]: 1L

In [5]: tr.GetEntry(0)
Out[5]: 342677

In [6]: tr.data

 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================

Thread 3 (Thread 0x7f307434a700 (LWP 19363)):
#0  sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:85
#1  0x0000000000564f1d in ?? ()
#2  0x000000000052c6d5 in PyEval_EvalFrameEx ()
#3  0x000000000055c594 in PyEval_EvalCodeEx ()
#4  0x000000000052ca8d in PyEval_EvalFrameEx ()
#5  0x000000000055c594 in PyEval_EvalCodeEx ()
#6  0x000000000052ca8d in PyEval_EvalFrameEx ()
#7  0x000000000056d0aa in ?? ()
#8  0x000000000052e1e6 in PyEval_EvalFrameEx ()
#9  0x000000000055c594 in PyEval_EvalCodeEx ()
#10 0x000000000052ca8d in PyEval_EvalFrameEx ()
#11 0x000000000052cf32 in PyEval_EvalFrameEx ()
#12 0x000000000052cf32 in PyEval_EvalFrameEx ()
#13 0x000000000056d0aa in ?? ()
#14 0x00000000004d9854 in ?? ()
#15 0x00000000004da20b in PyEval_CallObjectWithKeywords ()
#16 0x00000000005872b2 in ?? ()
#17 0x00007f3077c13182 in start_thread (arg=0x7f307434a700) at pthread_create.c:312
#18 0x00007f307794030d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

Thread 2 (Thread 0x7f30681c4700 (LWP 19375)):
#0  sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:85
#1  0x00000000005519f0 in ?? ()
#2  0x000000000052c6d5 in PyEval_EvalFrameEx ()
#3  0x000000000056d0aa in ?? ()
#4  0x000000000052e1e6 in PyEval_EvalFrameEx ()
#5  0x000000000052cf32 in PyEval_EvalFrameEx ()
#6  0x000000000052cf32 in PyEval_EvalFrameEx ()
#7  0x000000000056d0aa in ?? ()
#8  0x00000000004d9854 in ?? ()
#9  0x00000000004da20b in PyEval_CallObjectWithKeywords ()
#10 0x00000000005872b2 in ?? ()
#11 0x00007f3077c13182 in start_thread (arg=0x7f30681c4700) at pthread_create.c:312
#12 0x00007f307794030d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

Thread 1 (Thread 0x7f3078026740 (LWP 19362)):
#0  0x00007f30779069d9 in __libc_waitpid (pid=19378, stat_loc=stat_loc
entry=0x7fff5a232380, options=options
entry=0) at ../sysdeps/unix/sysv/linux/waitpid.c:40
#1  0x00007f307788b592 in do_system (line=<optimised out>) at ../sysdeps/posix/system.c:148
#2  0x00007f307216b0d3 in TUnixSystem::StackTrace() () from /home/steve/packages/root/v5_34_18/lib/libCore.so.5.34
#3  0x00007f307216cdbc in TUnixSystem::DispatchSignals(ESignals) () from /home/steve/packages/root/v5_34_18/lib/libCore.so.5.34
#4  <signal handler called>
#5  0x0000000000000000 in ?? ()
#6  0x00007f307213cfa9 in TClass::GetActualClass(void const*) const () from /home/steve/packages/root/v5_34_18/lib/libCore.so.5.34
#7  0x00007f307328807b in PyROOT::BindRootObject(void*, TClass*, bool) () from /home/steve/packages/root/v5_34_18/lib/libPyROOT.so
#8  0x00007f307328375b in PyROOT::TTreeGetAttr(PyROOT::ObjectProxy*, _object*) () from /home/steve/packages/root/v5_34_18/lib/libPyROOT.so
#9  0x00007f307328d65b in PyROOT::im_call(_object*, _object*, _object*) () from /home/steve/packages/root/v5_34_18/lib/libPyROOT.so
#10 0x000000000054a328 in PyObject_CallFunctionObjArgs ()
#11 0x0000000000598b5b in ?? ()
#12 0x00000000004ce73d in ?? ()
#13 0x000000000052c461 in PyEval_EvalFrameEx ()
#14 0x000000000055c594 in PyEval_EvalCodeEx ()
#15 0x00000000005b7392 in PyEval_EvalCode ()
#16 0x00000000005315d8 in PyEval_EvalFrameEx ()
#17 0x000000000055c594 in PyEval_EvalCodeEx ()
#18 0x000000000052ca8d in PyEval_EvalFrameEx ()
#19 0x000000000055c594 in PyEval_EvalCodeEx ()
#20 0x000000000052ca8d in PyEval_EvalFrameEx ()
#21 0x000000000055c594 in PyEval_EvalCodeEx ()
#22 0x000000000052ca8d in PyEval_EvalFrameEx ()
#23 0x000000000055c594 in PyEval_EvalCodeEx ()
#24 0x000000000052ca8d in PyEval_EvalFrameEx ()
#25 0x000000000055c594 in PyEval_EvalCodeEx ()
#26 0x000000000052ca8d in PyEval_EvalFrameEx ()
#27 0x000000000055c594 in PyEval_EvalCodeEx ()
#28 0x000000000052ca8d in PyEval_EvalFrameEx ()
#29 0x000000000056d0aa in ?? ()
#30 0x000000000052e1e6 in PyEval_EvalFrameEx ()
#31 0x000000000055c594 in PyEval_EvalCodeEx ()
#32 0x000000000052ca8d in PyEval_EvalFrameEx ()
#33 0x000000000055c594 in PyEval_EvalCodeEx ()
#34 0x00000000005b7392 in PyEval_EvalCode ()
#35 0x0000000000469663 in ?? ()
#36 0x00000000004699e3 in PyRun_FileExFlags ()
#37 0x0000000000469f1c in PyRun_SimpleFileExFlags ()
#38 0x000000000046ab81 in Py_Main ()
#39 0x00007f3077866ec5 in __libc_start_main (main=0x46ac3f <main>, argc=4, argv=0x7fff5a236398, init=<optimised out>, fini=<optimised out>, rtld_fini=<optimised out>, stack_end=0x7fff5a236388) at libc-start.c:287
#40 0x000000000057497e in _start ()
===========================================================


The lines below might hint at the cause of the crash.
If they do not help you then please submit a bug report at
http://root.cern.ch/bugs. Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.
===========================================================
#5  0x0000000000000000 in ?? ()
#6  0x00007f307213cfa9 in TClass::GetActualClass(void const*) const () from /home/steve/packages/root/v5_34_18/lib/libCore.so.5.34
#7  0x00007f307328807b in PyROOT::BindRootObject(void*, TClass*, bool) () from /home/steve/packages/root/v5_34_18/lib/libPyROOT.so
#8  0x00007f307328375b in PyROOT::TTreeGetAttr(PyROOT::ObjectProxy*, _object*) () from /home/steve/packages/root/v5_34_18/lib/libPyROOT.so
#9  0x00007f307328d65b in PyROOT::im_call(_object*, _object*, _object*) () from /home/steve/packages/root/v5_34_18/lib/libPyROOT.so
#10 0x000000000054a328 in PyObject_CallFunctionObjArgs ()
#11 0x0000000000598b5b in ?? ()
#12 0x00000000004ce73d in ?? ()
#13 0x000000000052c461 in PyEval_EvalFrameEx ()
#14 0x000000000055c594 in PyEval_EvalCodeEx ()
#15 0x00000000005b7392 in PyEval_EvalCode ()
#16 0x00000000005315d8 in PyEval_EvalFrameEx ()
#17 0x000000000055c594 in PyEval_EvalCodeEx ()
#18 0x000000000052ca8d in PyEval_EvalFrameEx ()
#19 0x000000000055c594 in PyEval_EvalCodeEx ()
#20 0x000000000052ca8d in PyEval_EvalFrameEx ()
#21 0x000000000055c594 in PyEval_EvalCodeEx ()
#22 0x000000000052ca8d in PyEval_EvalFrameEx ()
#23 0x000000000055c594 in PyEval_EvalCodeEx ()
#24 0x000000000052ca8d in PyEval_EvalFrameEx ()
#25 0x000000000055c594 in PyEval_EvalCodeEx ()
#26 0x000000000052ca8d in PyEval_EvalFrameEx ()
#27 0x000000000055c594 in PyEval_EvalCodeEx ()
#28 0x000000000052ca8d in PyEval_EvalFrameEx ()
#29 0x000000000056d0aa in ?? ()
#30 0x000000000052e1e6 in PyEval_EvalFrameEx ()
#31 0x000000000055c594 in PyEval_EvalCodeEx ()
#32 0x000000000052ca8d in PyEval_EvalFrameEx ()
#33 0x000000000055c594 in PyEval_EvalCodeEx ()
#34 0x00000000005b7392 in PyEval_EvalCode ()
#35 0x0000000000469663 in ?? ()
#36 0x00000000004699e3 in PyRun_FileExFlags ()
#37 0x0000000000469f1c in PyRun_SimpleFileExFlags ()
#38 0x000000000046ab81 in Py_Main ()
#39 0x00007f3077866ec5 in __libc_start_main (main=0x46ac3f <main>, argc=4, argv=0x7fff5a236398, init=<optimised out>, fini=<optimised out>, rtld_fini=<optimised out>, stack_end=0x7fff5a236388) at libc-start.c:287
#40 0x000000000057497e in _start ()
===========================================================

The other branches in the file are made with my own classes, and work as expected in both CINT and PyROOT. All 4 TObjArray branches exhibit the same behaviour, working correctly in CINT and segfaulting in PyROOT.

I’m using ROOT v5-34-18.

Hi,

could you post the file or a link to it?

The code in which it crashes is not called in CINT. This is PyROOT trying to auto-cast to the actual class. My guess is that a dictionary for the type used is missing (or not auto-loadable, or maybe partially uso). It could also be a deeper bug than that. But hard to say without reproducing first.

Thanks,
Wim

I’ve sent a PM with the file attached.

Hi,

is bug in the PyROOT Pythonization … I have a fix, but will need to write some extra tests to verify before committing. To work around, all I can think of is to use SetBranchAddress() like in C++ …

Thanks for reporting!

Cheers,
Wim

Thanks for the quick response. I’ll use SetBranchAddress for now.

Hi,

is in now … to be rolled up in the next patch release (also in trunk).

Cheers,
Wim