Crash in geometry after CheckOverlaps

Hello!

Please check if I am doing something wrong or this is a real bug. The following code crashes after running it several times (.x test.C), sometimes already the second time, sometimes after three or four re-runs:


#include "TGeoManager.h"
#include "TGeoMaterial.h"
#include "TGeoMedium.h"
#include "TGeoVolume.h"
#include "TCanvas.h"
void test()
{
    TGeoManager *geom = new TGeoManager("world", "wf");
    TGeoMaterial *matVacuum = new TGeoMaterial("Vacuum", 0, 0, 0);
    TGeoMedium *medVacuum = new TGeoMedium("Vacuum", 1, matVacuum);
    TGeoVolume *top = geom->MakeBox("top", medVacuum, 10.0, 10.0, 10.0);
    geom->SetTopVolume(top);
    TGeoVolume *sphere = geom->MakeSphere("sph", medVacuum, 0.0, 5.0);
    top->AddNode(sphere, 1);
    geom->CloseGeometry();
    geom->SetVisLevel();

    geom->CheckOverlaps(0.001); // comment away and there is no crash

    TCanvas *c1 = new TCanvas(“c1”, “Wireframe Geometry”, 800, 800);
    top->Draw("");
    c1->Update();
}

and does not crash if the line with geom->CheckOverlaps(0.001) is commented away.

Trace:

#6 0x00007d01096f836d in TGeoNodeCache::PopState(int&, double*) () from /opt/root6.40.02/root/lib/libGeom.so
#7 0x00007d01129ee0d9 in TGeoNavigator::PopPath() [clone .isra.0] () from /opt/root6.40.02/root/lib/libGeomPainter.so
#8 0x00007d01129f3c82 in TGeoPainter::DistanceToPrimitiveVol(TGeoVolume*, int, int) () from /opt/root6.40.02/root/lib/libGeomPainter.so
#9 0x00007d010acd3a33 in TPad::Pick(int, int, TObjLink*&) () from /opt/root6.40.02/root/lib/libGpad.so
#10 0x00007d010acaf2e0 in TCanvas::Pick(int, int, TObject*) () from /opt/root6.40.02/root/lib/libGpad.so
#11 0x00007d010aca9f4d in TCanvas::HandleInput(EEventType, int, int) () from /opt/root6.40.02/root/lib/libGpad.so
#12 0x00007d0108990c81 in TRootCanvas::HandleContainerMotion(Event_t*) () from /opt/root6.40.02/root/lib/libGui.so
#13 0x00007d01088785f8 in TGFrame::HandleEvent(Event_t*) () from /opt/root6.40.02/root/lib/libGui.so
#14 0x00007d010881428c in TGClient::HandleEvent(Event_t*) () from /opt/root6.40.02/root/lib/libGui.so
#15 0x00007d010881489d in TGClient::ProcessOneEvent() () from /opt/root6.40.02/root/lib/libGui.so
#16 0x00007d01088148ea in TGClient::HandleInput() () from /opt/root6.40.02/root/lib/libGui.so
#17 0x00007d012cf35a90 in TUnixSystem::DispatchOneEvent(bool) () from /opt/root6.40.02/root/lib/libCore.so
#18 0x00007d012ce2cc34 in TSystem::Run() () from /opt/root6.40.02/root/lib/libCore.so
#19 0x00007d012cdb0167 in TApplication::Run(bool) () from /opt/root6.40.02/root/lib/libCore.so
#20 0x00007d012d140665 in TRint::Run(bool) () from /opt/root6.40.02/root/lib/libRint.so
#21 0x00005d6b0e77c303 in main ()


Root version: 6.40.02

Downloaded binary for Ubuntu 24.04 Mate

Cheers,

Andrey

@agheata, could you have a look please?

Thanks for the report. I can reproduce this. CheckOverlaps runs multi-threaded, and each thread caches its navigator in a thread_local variable - this was constrained by the API. When launching the second time in the same process, the thread navigators are deleted, but the dangling pointers get reused since they cannot be cleaned by the master thread. Sorry for this complicated explanation, the bottom line is that I am looking for a fix. Meanwhile, you can add ROOT::EnableImplicitMT(1); before CheckOverlaps()

P.S This will be addressed by: [geom] Fix stale thread-local navigators across manager lifetimes by agheata · Pull Request #22937 · root-project/root · GitHub

Cheers,

Thank you Andrei!

The explanation makes sense, I have implemented your temporary fix in our toolkit, and there are no crashes. I will keep an eye and when you have a permanent fix, enable multi-threading back.

Cheers,

Andrey