Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

[PyROOT] Segfault at exit deleting a branch with a Cling-generated collection destructor after cppyy instantiated a template

Abierto
#23,728 9 comentarios 0 reacciones 1 asignado Ver en GitHub

Los mantenedores suelen responder en 1 día

@guitargeek ya está trabajando en esto.

Desde el 16/10/2026.

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
12/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
cpp, python
Área
compilers

Línea de trabajo

Start by running the reproducer script in the issue on a ROOT build with cppyy enabled, then check the backtrace. The crash is in the Cling-generated destructor reached through TClingCallFunc::ExecDestructor from TBranchElement::ReleaseObject, during TROOT::EndOfProcessCleanups at exit. Done means the script exits cleanly with and without the ROOT.std.vector[ROOT.TNamed]() line, which needs a root-cause fix in the interpreter rather than a LinkDef workaround.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug in:Python Interface test wit cppjit
Check duplicate issues.
  • Checked for duplicates
Description

A Python script segfaults at exit (sometimes it aborts with corrupted double-linked list instead) when both of these hold:

  1. a TTree branch whose collection type has no compiled dictionary (here std::vector<std::vector<int>>) has been read, and the file is deleted by TROOT::EndOfProcessCleanups at exit;
  2. the script has constructed, through cppyy, an object of a class template specialisation that was not instantiated before, e.g. ROOT.std.vector[ROOT.TNamed]() or ROOT.std.shared_ptr[ROOT.TObject]().

(Discovered originally with Objects held by shared pointers)

Each condition alone exits cleanly. The crash is in the Cling-generated destructor of the collection, called when the branch is deleted:

 *** Break *** segmentation violation
 0x... in TClingCallFunc::ExecDestructor(TClingClassInfo const*, void*, unsigned long, bool) + 0x39
 0x... in TClingClassInfo::Delete(void*, ROOT::TMetaUtils::TNormalizedCtxt const&) const
 0x... in TBranchElement::ReleaseObject() + 0x143
 0x... in TBranchElement::ResetAddress() + 0xb0
 0x... in TBranchElement::~TBranchElement()
 0x... in TObjArray::Delete(char const*) + 0x6c
 0x... in TTree::~TTree()
 0x... in THashList::Delete(char const*) + 0x339
 0x... in TROOT::EndOfProcessCleanups() + 0x9e
 0x... in <unknown> (libc exit handlers)
 0x... in __libc_start_main + 0x88

(backtrace from 6.36.14; on 6.40 the frames above TBranchElement::ReleaseObject show up as <unknown> from libCling.so.)

Other things we saw while narrowing it down:

  • Only constructing an object triggers it. Looking up the type (ROOT.std.shared_ptr[ROOT.TObject] without calling it) does not, and neither does instantiating the same type through the interpreter (ROOT.gInterpreter.ProcessLine("std::shared_ptr<TObject> p;")).
  • Without reading an entry (t.GetEntry(0) removed) it exits cleanly.
  • Calling ROOT.gROOT.EndOfProcessCleanups() explicitly at the end of the script, while Python is still alive, exits cleanly. So the crash needs the cleanup to run from the C atexit handler, after Py_Finalize.
  • Generating a dictionary for the collection type (ROOT.gInterpreter.GenerateDictionary("vector<vector<int> >", "vector")) avoids it, since the destructor then no longer goes through TClingCallFunc.

We hit this in a real analysis (FairShip, https://github.com/ShipSoft/FairShip/pull/1478), where the file is kept alive until exit as a friend of a tree and the Python code creates a std::shared_ptr<genfit::DetPlane>. There we work around it by adding the collection types to our LinkDefs.

Reproducer
import subprocess
import sys

import ROOT

FILENAME = "vv.root"

if sys.argv[1:] == ["write"]:
    f = ROOT.TFile(FILENAME, "RECREATE")
    t = ROOT.TTree("t", "t")
    v = ROOT.std.vector[ROOT.std.vector[int]]()  # no compiled dictionary for this type
    t.Branch("vv", v)
    v.push_back(ROOT.std.vector[int]([1, 2]))
    t.Fill()
    f.Write()
    f.Close()
    sys.exit(0)

subprocess.run([sys.executable, __file__, "write"], check=True)

f = ROOT.TFile(FILENAME)
ROOT.SetOwnership(f, False)  # let TROOT::EndOfProcessCleanups delete it at exit
t = f.Get("t")
t.GetEntry(0)

ROOT.std.vector[ROOT.TNamed]()  # any new template instantiation constructed via cppyy

print("end of script")

python repro.py prints end of script and then crashes. Results over 5 runs each:

ROOT result
6.40.04 segfault 5/5
6.40.02 crash 5/5 (one of them a SIGTRAP, one a SIGSEGV without ROOT's stack trace)
6.36.14 segfault 2/5, corrupted double-linked list abort 3/5

Commenting out the ROOT.std.vector[ROOT.TNamed]() line, it exits cleanly.

ROOT version

6.40.04 (also 6.40.02 and 6.36.14)

Installation method

conda-forge (root package, via pixi), Python 3.13

Operating system

Linux x86_64 (NixOS, glibc 2.42)

Additional context

No response

Lenguaje dominante
C++
Estrellas
3.3k
Forks
1.6k
Merge medio
2 d 17 h
PR fusionados (30 d)
188

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de root-project/root

Todos los issues de root-project/root

Issues similares

Más issues de C++

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.