Exit code 129 when circling through entries and leaves (python)

TLDR: Error code 129 when cycling through a dictionary holding data dictionaries divided by detectors. Code is attached below; Error is attached via pastebin; root file is attached below. OS - ubuntu 22.04, root version 6.26/04

Hello all,

I have a Root file of the following hierarchy, outputted by G4Beamline simulation software:
image

TFile->TDirectoryFile->Trees->Leaves (with different entries).

I try to run through the leaves’ entries in order to save them into excel. The following leaves are available:

['x', 'y', 'z', 'Px', 'Py', 'Pz', 't', 'PDGid', 'EventID', 'TrackID', 'ParentID', 'Weight', 'Edep', 'VisibleEdep', 'Ntracks']

With a total of 2118 entries.

The data structure that holds the simulation results is as the following:

detectors_data={
Det1:{'x':[list_of_all_x_values], 'y':[list_of_all_y_values],...},
Det2:{'x':[list_of_all_x_values], 'y':[list_of_all_y_values],...}
}

detectors_data is the dictionary that holds all the detectors and their datas.

Det1,...,Det5 are the inner dictionaries that actually hold each data that was recorded on each detector. The keys for these dictionaries are the leave’s names.

When trying to save data from all the entries under ‘x’ leaf, everything goes smoothly. When changing to ‘y’ leaf, the program crashes with exit code 129, signal 1: SIGHUP
Attached is the python file and the ROOT file it is meant to run with.

1200000.root (371.9 KB)

test.py (1.5 KB)

Crash report

OS - ubuntu 22.04, root version 6.26/04

I would appreciate any help!
Thanks!

Hi @JordanCarmel,

The important thing here is not the exit code 129, but the SIGSEGV and the corresponding stack traces (thanks for providing the output via pastebin!).

 *** Break *** segmentation violation
 
 
 
===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
 
Thread 21 (Thread 0x7fd9e48db640 (LWP 68120) "python"):
#0  0x00007fda3a0ea49f in __GI___wait4 (pid=68123, stat_loc=stat_loc
entry=0x7fd9e48d5268, options=options
entry=0, usage=usage
entry=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
#1  0x00007fda3a0ea41b in __GI___waitpid (pid=<optimized out>, stat_loc=stat_loc
entry=0x7fd9e48d5268, options=options
entry=0) at ./posix/waitpid.c:38
#2  0x00007fda3a050bcb in do_system (line=<optimized out>) at ../sysdeps/posix/system.c:171
#3  0x00007fda0d1172d4 in TUnixSystem::StackTrace() () from /home/jordan/root/lib/libCore.so.6.26
#4  0x00007fda367c3ff3 in (anonymous namespace)::TExceptionHandlerImp::HandleException(int) () from /home/jordan/root/lib/libcppyy_backend3_10.so.6.26
#5  0x00007fda0d114469 in TUnixSystem::DispatchSignals(ESignals) () from /home/jordan/root/lib/libCore.so.6.26
#6  <signal handler called>
#7  0x000055e00deaf445 in PyMem_Malloc ()

The fact that it crashes during MyMem_Malloc() tells me that probably some structure used by the allocator has been corrupted already at this point.

Taking a look at the code that you provided, concretely at the excerpt below

        for leaf in leaf_list:
            leaf_value = array('f', [0])  # Create a variable to hold the leaf value
            leaf_values = []
            detectors[detector].SetBranchAddress(leaf.GetName(), leaf_value)
            for entry in range(detectors[detector].GetEntries()):
                detectors[detector].GetEntry(entry)
                leaf_values.append(leaf_value[0])
            # print(f"\tAdding {leaf}'s data to {detector} list...")
            detectors_data[detector][leaf.GetName()] = leaf_values

makes the problem apparent: each iteration of the outer loop (i.e., for leaf in leaf_list), is calling SetBranchAddress() on a loop-local variable – note that previous calls to SetBranchAddress() are still effective, but the pointed-to address is not valid anymore.

Slightly modifying the code to reset the address of a branch, as in

        for leaf in leaf_list:
            leaf_value = array('f', [0])  # Create a variable to hold the leaf value
            leaf_values = []
            detectors[detector].SetBranchAddress(leaf.GetName(), leaf_value)
            for entry in range(detectors[detector].GetEntries()):
                detectors[detector].GetEntry(entry)
                leaf_values.append(leaf_value[0])
            detectors[detector].SetBranchAddress(leaf.GetName(), ROOT.nullptr)
            # print(f"\tAdding {leaf}'s data to {detector} list...")
            detectors_data[detector][leaf.GetName()] = leaf_values

makes it work.

However, please note that the provided code is highly inefficient as-is (i.e., iterating the TTree multiple times). I’d suggest to rewrite it in order to iterate over the TTree entries just once.

(also, FYI: @vpadulan)

Cheers,
J.

2 Likes

BTW, @JordanCarmel, consider marking this topic as solved if you are happy with the solution above.

It does in fact work, thank you. Took me a second to adjust the full code (I sent the bare minimum required to replicate).

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.