Skip to content

Erroneous values and crash in TTreePlayer when mixing many TChains and friendship #20033

@lmoureaux

Description

@lmoureaux

Check duplicate issues.

  • Checked for duplicates

Description

Adding one TChain to the case of #16805 yields the exact same erroneous behaviour:

  • Branches stop updating at the first file boundary
  • TTreePlayer crashes at the same location

Reproducer

root -l -q bugDemo.C

#include <TChain.h>
#include <TFile.h>
#include <TTree.h>

using namespace std;

/**
 * Creates a file with a tree, and fills the \c index branch in the tree with
 * numbers in [first, last).
 */
void createFile(const char* name, int first, int last)
{
    TFile file(name, "RECREATE");
    TTree tree("", "");

    int index, value = 0;
    auto branch = tree.Branch("index", &index);
    tree.Branch("value", &value); // This will be a constant 0

    for (index = first; index < last; ++index) tree.Fill();

    file.WriteObject(&tree, "tree");
    file.Close();
}

void bugDemo()
{
    createFile("friends-hybrid-step0-0.root",  0, 10);
    createFile("friends-hybrid-step0-1.root", 10, 20);

    // Create a chain
    auto chain = make_unique<TChain>("tree");
    chain->Add("friends-hybrid-step0-0.root");
    chain->Add("friends-hybrid-step0-1.root");

    {
        auto newTree = make_unique<TTree>("tree", "");

        // Add (empty) entries to the tree.
        for (int i = 0; i < chain->GetEntries(); ++i) {
            newTree->Fill();
        }

        // Save the tree to a file, otherwise GetEntry() doesn't load branches
        // from the friend.
        TFile f("friends-hybrid-step1.root", "RECREATE");
        f.WriteObject(newTree.get(), "tree");
    }

    auto chain2 = make_unique<TChain>("tree");
    chain2->Add("friends-hybrid-step1.root");
    chain2->GetEntry(0); // Load the tree
    chain2->GetTree()->AddFriend(chain.get());

    // Now we have:
    //   chain2 -> empty tree -> chain -> file1,file2
    // Let's add another chain
    auto chain3 = make_unique<TChain>("tree");
    chain3->Add("friends-hybrid-step1.root");
    chain3->GetEntry(0); // Load the tree
    chain3->GetTree()->AddFriend(chain2.get());

    // Now we have:
    //   chain3 -> empty tree -> chain2 -> empty tree -> chain -> file1,file2
    // Now iterate over the tree and check the contents of the branches
    // inherited from the friends.

    // Load branches
    int index = -1, value = -1;
    cout << boolalpha << ( chain3->SetBranchAddress("index", &index) == 0 ) << endl;
    cout << boolalpha << ( chain3->SetBranchAddress("value", &value) == 0 ) << endl;

    // Loop. This should go over both files.
    for (int i = 0; i < chain3->GetEntries(); ++i) {
        cout << boolalpha << ( chain3->GetEntry(i) > 0 ) << " "
             << boolalpha << ( index == i ) << " "
             << boolalpha << ( value == 0 )
             << endl;
    }

    // Let's crash TTreePlayer
    chain3->Scan("index:value");
}

I get:

true
true
true true true
true true true
true true true
true true true
true true true
true true true
true true true
true true true
true true true
true true true
true false true
true false true
true false true
true false true
true false true
true false true
true false true
true false true
true false true
true false true
************************************
*    Row   *     index *     value *
************************************
*        0 *         0 *         0 *
*        1 *         1 *         0 *
*        2 *         2 *         0 *
*        3 *         3 *         0 *
*        4 *         4 *         0 *
*        5 *         5 *         0 *
*        6 *         6 *         0 *
*        7 *         7 *         0 *
*        8 *         8 *         0 *
*        9 *         9 *         0 *

 *** Break *** segmentation violation

Expected output is only true followed by the Scan output.

ROOT version

   ------------------------------------------------------------------
  | Welcome to ROOT 6.37.01                        https://root.cern |
  | (c) 1995-2025, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on Oct 05 2025, 16:05:13                 |
  | From heads/master@v6-37-01-8374-gc3f701983c                      |
  | With g++ (GCC) 15.1.0                                            |
  | Try '.help'/'.?', '.demo', '.license', '.credits', '.quit'/'.q'  |
   ------------------------------------------------------------------

Installation method

LCG nightlies, built from source

Operating system

Linux (lxplus)

Additional context

https://gitlab.cern.ch/cms-analysis/general/DasAnalysisSystem/Core/-/merge_requests/268

Metadata

Metadata

Assignees

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions