From 9e35a4f0fe54b8cdda4c107610a4df53f07a5022 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Wed, 30 Sep 2026 13:17:58 +0200 Subject: [PATCH] Use std::threads instead of TBB tasks in the o2-sim hit merger This fixes a crash of the o2-sim hit merger at the end of a run. - The concurrent flush of kinematics and detector files used a tbb::task_group and tbb::parallel_for_each. - It runs on a merger IO thread that is created anew for every merge batch. - When such a thread exits, TBB releases its thread pool and can segfault in pthread_detach. - The flush now uses std::threads that are joined before the function returns. Co-Authored-By: Claude Sonnet 5.5 --- run/O2HitMerger.cxx | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/run/O2HitMerger.cxx b/run/O2HitMerger.cxx index 3fabb31193b7d..b79c18bd5ca7a 100644 --- a/run/O2HitMerger.cxx +++ b/run/O2HitMerger.cxx @@ -84,8 +84,7 @@ #endif #include -#include -#include +#include namespace o2 { @@ -767,8 +766,9 @@ bool O2HitMerger::mergeAndFlushData() eventheader->putInfo("prims_total", prims); }; // the kinematics and each detector go to separate files, so we merge and flush them concurrently - tbb::task_group tasks; - tasks.run([&]() { + // plain threads, since the TBB pool teardown crashed the merger + std::vector tasks; + tasks.emplace_back([&]() { reorderAndMergeMCTracks(flusheventID, mOutTree, nprimaries, subevOrdered, mcheaderhook, eventheader); if (mOutTree) { @@ -796,13 +796,15 @@ bool O2HitMerger::mergeAndFlushData() auto& det = mDetectorInstances[id]; auto hittree = det ? mDetectorToTTreeMap[id] : nullptr; if (hittree) { - tasks.run([&, det = det.get(), hittree]() { + tasks.emplace_back([&, det = det.get(), hittree]() { det->mergeHitEntriesAndFlush(flusheventID, *hittree, trackoffsets, nprimaries, subevOrdered); hittree->SetEntries(hittree->GetEntries() + 1); }); } } - tasks.wait(); + for (auto& t : tasks) { + t.join(); + } cleanEvent(flusheventID); LOG(info) << "Merge/flush for event " << flusheventID << " took " << timer.RealTime(); @@ -815,7 +817,13 @@ bool O2HitMerger::mergeAndFlushData() files.push_back(mDetectorOutFiles[id]); } } - tbb::parallel_for_each(files, [](TFile* file) { file->Write("", TObject::kOverwrite); }); + std::vector writers; + for (auto file : files) { + writers.emplace_back([file]() { file->Write("", TObject::kOverwrite); }); + } + for (auto& t : writers) { + t.join(); + } } return true; }