[PyROOT] Segfault at exit deleting a branch with a Cling-generated collection destructor after cppyy instantiated a template
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
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
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:
- a TTree branch whose collection type has no compiled dictionary (here
std::vector<std::vector<int>>) has been read, and the file is deleted byTROOT::EndOfProcessCleanupsat exit; - 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]()orROOT.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 Catexithandler, afterPy_Finalize. - Generating a dictionary for the collection type (
ROOT.gInterpreter.GenerateDictionary("vector<vector<int> >", "vector")) avoids it, since the destructor then no longer goes throughTClingCallFunc.
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
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de root-project/root
-
thisroot.sh: wrong ROOTSYS in zsh when the shell's command line has a newlinePosiblemente ocupada @dpiparo la tomó hace 5 días. Abiertobug in:Build System
Dificultad 2/5 1-3 horas Aptitud para principiantes 86/100
root-project/root#23746 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
[tmva][sofie] Inputs of unsupported type (e.g. float16) give code that does not compile instead of an errorPosiblemente ocupada @lmoneta la tomó hace 14 días. AbiertoAI-Assisted bug in:SOFIE
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
root-project/root#23655 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
[RDataFrame] Code that transforms `#var` alias to `R_rdf_sizeof_var` does not respect string literalsPosiblemente ocupada @vepadulano la tomó hace 2 días. Abiertobug in:RDataFrame
Dificultad 3/5 1-2 días Aptitud para principiantes 71/100
root-project/root#23790 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
TDataMember::GetOffset interfers to TDataMember::GetOffsetCintPosiblemente ocupada @pcanal la tomó hace 2 días. Abiertobug in:Core Libraries
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
root-project/root#23777 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
`TChain::GetEntries` internal caching ineffective?Posiblemente ocupada @pcanal la tomó hace 7 días. Abiertoimprovement in:TTree
root-project/root#23738 · 6 comentarios · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de root-project/root
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
OpenSpace/OpenSpace#4353 · 1 comentario ·
Los mantenedores suelen responder en 5 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
-
macOS: a double-click on a notarized altairsim is refused, and the docs give only the offline casePosiblemente ocupada @anhaoXie la tomó hoy. Abiertodocumentation
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
mutationpp/Mutationpp#337 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
bulletphysics/bullet3#4819 ·