From 2a0a2fac95295db9eed9a1594c97023c35a47f5c Mon Sep 17 00:00:00 2001 From: Jakob Blomer Date: Wed, 8 Jul 2026 16:10:36 +0200 Subject: [PATCH 1/8] [ci] fix picking up ASAN configuration --- .../buildconfig/{alma10-minimal-asan.txt => alma10-asan.txt} | 0 .github/workflows/root-ci.yml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/root-ci-config/buildconfig/{alma10-minimal-asan.txt => alma10-asan.txt} (100%) diff --git a/.github/workflows/root-ci-config/buildconfig/alma10-minimal-asan.txt b/.github/workflows/root-ci-config/buildconfig/alma10-asan.txt similarity index 100% rename from .github/workflows/root-ci-config/buildconfig/alma10-minimal-asan.txt rename to .github/workflows/root-ci-config/buildconfig/alma10-asan.txt diff --git a/.github/workflows/root-ci.yml b/.github/workflows/root-ci.yml index a7820f201a3f4..e81aeb1f825e0 100644 --- a/.github/workflows/root-ci.yml +++ b/.github/workflows/root-ci.yml @@ -442,7 +442,7 @@ jobs: overrides: ["CMAKE_CXX_STANDARD=20"] # Asan build - image: alma10 - platform_config: alma10-minimal + platform_config: alma10-asan is_special: true property: "asan" overrides: ["ROOT_CTEST_CUSTOM_FLAGS=-E@\\(^tutorial-\\|cppinterop-CppInterOpTest\\|roottest-cling-specialobj-runf02$\\|roottest-root-collection-DeleteWarning$\\|roottest-root-io-evolution-fixarr2$\\|roottest-root-meta-rlibmap$\\|roottest-root-treeproxy-vectorint-vectorint$\\)"] From a20a1793ca5b9058f650c4a662ea06f7dbfd4a93 Mon Sep 17 00:00:00 2001 From: Jakob Blomer Date: Mon, 29 Jun 2026 11:00:47 +0200 Subject: [PATCH 2/8] [ci] fix up asan build config --- .../workflows/root-ci-config/buildconfig/alma10-asan.txt | 6 +++--- .github/workflows/root-ci.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/root-ci-config/buildconfig/alma10-asan.txt b/.github/workflows/root-ci-config/buildconfig/alma10-asan.txt index d9e43b53bbff4..6cf8a854af8fb 100644 --- a/.github/workflows/root-ci-config/buildconfig/alma10-asan.txt +++ b/.github/workflows/root-ci-config/buildconfig/alma10-asan.txt @@ -1,12 +1,12 @@ -CMAKE_BUILD_TYPE=Debug -CMAKE_CXX_FLAGS_DEBUG="-Og -g" +CMAKE_BUILD_TYPE=RelWithDebInfo asan=ON ccache=ON builtin_civetweb=ON builtin_vdt=ON +ccache=ON fail-on-missing=ON minimal=ON roottest=ON testing=ON LSAN_OPTIONS=verbosity=1:log_threads=1 -ROOT_CTEST_CUSTOM_FLAGS="-E \(cppinterop-CppInterOpTest\|roottest-cling-specialobj-runf02$\|roottest-root-collection-DeleteWarning$\|roottest-root-io-evolution-fixarr2$\|roottest-root-meta-rlibmap$\|roottest-root-treeproxy-vectorint-vectorint$\)" +ROOT_CTEST_CUSTOM_FLAGS="-E \(cppinterop-CppInterOpTest\|gtest-core-metacling-TClingTest$\|roottest-cling-specialobj-runf02$\|roottest-root-collection-DeleteWarning$\|roottest-root-io-evolution-fixarr2$\|roottest-root-meta-rlibmap$\|roottest-root-tree-cloning-runtreeCloneTest2$\|roottest-root-treeproxy-vectorint-vectorint$\)" diff --git a/.github/workflows/root-ci.yml b/.github/workflows/root-ci.yml index e81aeb1f825e0..7653b58497e60 100644 --- a/.github/workflows/root-ci.yml +++ b/.github/workflows/root-ci.yml @@ -445,7 +445,7 @@ jobs: platform_config: alma10-asan is_special: true property: "asan" - overrides: ["ROOT_CTEST_CUSTOM_FLAGS=-E@\\(^tutorial-\\|cppinterop-CppInterOpTest\\|roottest-cling-specialobj-runf02$\\|roottest-root-collection-DeleteWarning$\\|roottest-root-io-evolution-fixarr2$\\|roottest-root-meta-rlibmap$\\|roottest-root-treeproxy-vectorint-vectorint$\\)"] + overrides: ["ROOT_CTEST_CUSTOM_FLAGS=-E@\\(^tutorial-\\|cppinterop-CppInterOpTest\\|gtest-core-metacling-TClingTest$\\|roottest-cling-specialobj-runf02$\\|roottest-root-collection-DeleteWarning$\\|roottest-root-io-evolution-fixarr2$\\|roottest-root-meta-rlibmap$\\|roottest-root-tree-cloning-runtreeCloneTest2$\\|roottest-root-treeproxy-vectorint-vectorint$\\)"] # Fedora Rawhide with Python freethreading+debug build - image: rawhide python_venv: "/py-venv-3.15td/ROOT-CI" From 1557aee5512aa8e9c80c6357e7b52ee273a5abf6 Mon Sep 17 00:00:00 2001 From: silverweed Date: Tue, 28 Jul 2026 09:14:29 +0200 Subject: [PATCH 3/8] Revert "[core] do not interrupt build when an asan error is found" This reverts commit d8695bed46d79d69025d8b369b8d4251fcae116b. --- core/sanitizer/SanitizerSetup.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/sanitizer/SanitizerSetup.cxx b/core/sanitizer/SanitizerSetup.cxx index 2e4b1340900dc..a638ccae054f5 100644 --- a/core/sanitizer/SanitizerSetup.cxx +++ b/core/sanitizer/SanitizerSetup.cxx @@ -31,8 +31,7 @@ const char* __asan_default_options() { ":detect_container_overflow=1" ":alloc_dealloc_mismatch=0" DETECT_LEAKS - ":verify_asan_link_order=0" - ":halt_on_error=0"; + ":verify_asan_link_order=0"; } /// Default options when leak sanitizer starts up in ROOT executables. From 61a05f32e4ac5dc66d9a60582a8a301d953ab3f7 Mon Sep 17 00:00:00 2001 From: silverweed Date: Tue, 28 Jul 2026 14:27:29 +0200 Subject: [PATCH 4/8] [CI] re-enable some tests in the asan build --- .github/workflows/root-ci-config/buildconfig/alma10-asan.txt | 2 +- .github/workflows/root-ci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/root-ci-config/buildconfig/alma10-asan.txt b/.github/workflows/root-ci-config/buildconfig/alma10-asan.txt index 6cf8a854af8fb..65f3fd63f791a 100644 --- a/.github/workflows/root-ci-config/buildconfig/alma10-asan.txt +++ b/.github/workflows/root-ci-config/buildconfig/alma10-asan.txt @@ -9,4 +9,4 @@ minimal=ON roottest=ON testing=ON LSAN_OPTIONS=verbosity=1:log_threads=1 -ROOT_CTEST_CUSTOM_FLAGS="-E \(cppinterop-CppInterOpTest\|gtest-core-metacling-TClingTest$\|roottest-cling-specialobj-runf02$\|roottest-root-collection-DeleteWarning$\|roottest-root-io-evolution-fixarr2$\|roottest-root-meta-rlibmap$\|roottest-root-tree-cloning-runtreeCloneTest2$\|roottest-root-treeproxy-vectorint-vectorint$\)" +ROOT_CTEST_CUSTOM_FLAGS="-E \(gtest-core-metacling-TClingTest$\|roottest-cling-specialobj-runf02$\|roottest-root-collection-DeleteWarning$\|roottest-root-io-evolution-fixarr2$\|roottest-root-meta-rlibmap$\|roottest-root-tree-cloning-runtreeCloneTest2$\|roottest-root-treeproxy-vectorint-vectorint$\)" diff --git a/.github/workflows/root-ci.yml b/.github/workflows/root-ci.yml index 7653b58497e60..0da9c83aa686d 100644 --- a/.github/workflows/root-ci.yml +++ b/.github/workflows/root-ci.yml @@ -445,7 +445,7 @@ jobs: platform_config: alma10-asan is_special: true property: "asan" - overrides: ["ROOT_CTEST_CUSTOM_FLAGS=-E@\\(^tutorial-\\|cppinterop-CppInterOpTest\\|gtest-core-metacling-TClingTest$\\|roottest-cling-specialobj-runf02$\\|roottest-root-collection-DeleteWarning$\\|roottest-root-io-evolution-fixarr2$\\|roottest-root-meta-rlibmap$\\|roottest-root-tree-cloning-runtreeCloneTest2$\\|roottest-root-treeproxy-vectorint-vectorint$\\)"] + overrides: ["ROOT_CTEST_CUSTOM_FLAGS=-E@\\(^tutorial-\\|gtest-core-metacling-TClingTest$\\|roottest-cling-specialobj-runf02$\\|roottest-root-collection-DeleteWarning$\\|roottest-root-io-evolution-fixarr2$\\|roottest-root-meta-rlibmap$\\|roottest-root-tree-cloning-runtreeCloneTest2$\\|roottest-root-treeproxy-vectorint-vectorint$\\)"] # Fedora Rawhide with Python freethreading+debug build - image: rawhide python_venv: "/py-venv-3.15td/ROOT-CI" From 11d503f8c16b29f32dfe111313055e42d7637e87 Mon Sep 17 00:00:00 2001 From: silverweed Date: Thu, 30 Jul 2026 09:20:55 +0200 Subject: [PATCH 5/8] [CI] disable odr violation asan checks for now There are too many failing tests with it --- core/sanitizer/SanitizerSetup.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/sanitizer/SanitizerSetup.cxx b/core/sanitizer/SanitizerSetup.cxx index a638ccae054f5..e4d783ace554b 100644 --- a/core/sanitizer/SanitizerSetup.cxx +++ b/core/sanitizer/SanitizerSetup.cxx @@ -31,7 +31,8 @@ const char* __asan_default_options() { ":detect_container_overflow=1" ":alloc_dealloc_mismatch=0" DETECT_LEAKS - ":verify_asan_link_order=0"; + ":verify_asan_link_order=0" + ":detect_odr_violation=0"; } /// Default options when leak sanitizer starts up in ROOT executables. From 112e918255d3d0ba5367798e8e995448ce2ae09b Mon Sep 17 00:00:00 2001 From: silverweed Date: Wed, 5 Aug 2026 09:14:44 +0200 Subject: [PATCH 6/8] [io] Fix roottest failing with Asan --- roottest/root/io/heritstl/SEIdAltLItem.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/roottest/root/io/heritstl/SEIdAltLItem.h b/roottest/root/io/heritstl/SEIdAltLItem.h index f5b06fae1822f..84d102893d27a 100644 --- a/roottest/root/io/heritstl/SEIdAltLItem.h +++ b/roottest/root/io/heritstl/SEIdAltLItem.h @@ -34,10 +34,10 @@ class SEIdAltLItem { fSigLin(siglin), fSigCorr(sigcorr), fTime(time) { }; - SEIdAltLItem(const SEIdAltLItem& that) // copy ctor - { *this = that; } + SEIdAltLItem(const SEIdAltLItem &) = default; + SEIdAltLItem &operator=(const SEIdAltLItem &) = default; - virtual ~SEIdAltLItem() { ; } // dtor + virtual ~SEIdAltLItem() = default; Int_t GetSEId() const { return fStripEndId; } Float_t GetWeight() const { return fWeight; } From 9fe881a835396e2cb19231f2c34a4ac3336fbe3c Mon Sep 17 00:00:00 2001 From: silverweed Date: Wed, 5 Aug 2026 14:22:46 +0200 Subject: [PATCH 7/8] [core] some ACLiC cleanups --- core/base/src/TSystem.cxx | 92 +++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/core/base/src/TSystem.cxx b/core/base/src/TSystem.cxx index 12a79480a7ff9..e7a725a73790d 100644 --- a/core/base/src/TSystem.cxx +++ b/core/base/src/TSystem.cxx @@ -2593,14 +2593,12 @@ static void R__WriteDependencyFile(const TString & build_loc, const TString &dep // standard include directories, bool needToUnlinkTempFile = false; -#ifndef WIN32 - const char * stderrfile = "/dev/null"; -#else + TString stderrfile = "/dev/null"; +#ifdef WIN32 // Determine the null device based on the shell in use. // COMSPEC unset or pointing to cmd.exe -> NUL // COMSPEC pointing to powershell -> $null // Anything else (e.g. bash/sh on Windows) -> `depfilename`.stderr.tmp - TString stderrfile; const char *comspec = gSystem->Getenv("COMSPEC"); if (!comspec || !comspec[0]) { stderrfile = "NUL"; @@ -2620,11 +2618,19 @@ static void R__WriteDependencyFile(const TString & build_loc, const TString &dep #endif TString bakdepfilename = depfilename + ".bak"; -#ifdef WIN32 - TString touch = "echo # > "; touch += "\"" + depfilename + "\""; -#else - TString touch = "echo > "; touch += "\"" + depfilename + "\""; -#endif + struct Defer { + bool fNeedToUnlinkTempFile; + const TString &fStderrfile, &fBakdepfilename; + ~Defer() + { + if (fNeedToUnlinkTempFile) { + // Remove the temporary stderr file if it was created. + gSystem->Unlink(fStderrfile); + } + gSystem->Unlink(fBakdepfilename); + } + } deferGuard{needToUnlinkTempFile, stderrfile, bakdepfilename}; + TString builddep = "rmkdepend"; gSystem->PrependPathName(TROOT::GetBinDir(), builddep); builddep += " \"-f"; @@ -2678,7 +2684,7 @@ static void R__WriteDependencyFile(const TString & build_loc, const TString &dep builddep += stderrfile; builddep += " 2>&1 "; - TString adddictdep = "echo "; + TString adddictdep; R__AddPath(adddictdep,targetname); adddictdep += ": "; #if defined(R__HAS_CLING_DICTVERSION) @@ -2694,19 +2700,27 @@ static void R__WriteDependencyFile(const TString & build_loc, const TString &dep } #endif { - const char *dictHeaders[] = { "RVersion.h", "ROOT/RConfig.hxx", "TClass.h", - "TDictAttributeMap.h","TInterpreter.h","TROOT.h","TBuffer.h", - "TMemberInspector.h","TError.h","RtypesImp.h","TIsAProxy.h", - "TFileMergeInfo.h","TCollectionProxyInfo.h"}; - - for (unsigned int h=0; h < sizeof(dictHeaders)/sizeof(dictHeaders[0]); ++h) - { - char *rootVersion = gSystem->Which(incPath,dictHeaders[h]); + constexpr const char *dictHeaders[] = {"RVersion.h", + "ROOT/RConfig.hxx", + "TClass.h", + "TDictAttributeMap.h", + "TInterpreter.h", + "TROOT.h", + "TBuffer.h", + "TMemberInspector.h", + "TError.h", + "RtypesImp.h", + "TIsAProxy.h", + "TFileMergeInfo.h", + "TCollectionProxyInfo.h"}; + + for (const char *header : dictHeaders) { + char *rootVersion = gSystem->Which(incPath, header); if (rootVersion) { R__AddPath(adddictdep,rootVersion); delete [] rootVersion; } else { - R__AddPath(adddictdep,rootsysInclude + "/" + dictHeaders[h]); + R__AddPath(adddictdep, rootsysInclude + "/" + header); } adddictdep += " "; } @@ -2720,32 +2734,36 @@ static void R__WriteDependencyFile(const TString & build_loc, const TString &dep delete [] rootCling; } } - adddictdep += " >> \""+depfilename+"\""; - TString addversiondep( "echo "); - addversiondep += libname + version_var_prefix + " \"" + ROOT_RELEASE + "\" >> \""+depfilename+"\""; + { + std::ofstream depFile(depfilename, std::ios::out | std::ios::trunc); + if (!depFile) { + ::Warning("ACLiC", "Failed to open dependency file %s for %s", depfilename.Data(), library.Data()); + return; + } +#ifdef WIN32 + depFile << "#\n"; +#endif + } - if (gDebug > 4) { - ::Info("ACLiC", "%s", touch.Data()); + if (gDebug > 4) { ::Info("ACLiC", "%s", builddep.Data()); ::Info("ACLiC", "%s", adddictdep.Data()); } + bool depbuiltOk = !gSystem->Exec(builddep); + if (!depbuiltOk) { + ::Warning("ACLiC", "Failed to run rmkdepend for %s", library.Data()); + return; + } - Int_t depbuilt = !gSystem->Exec(touch); - if (depbuilt) depbuilt = !gSystem->Exec(builddep); - if (depbuilt) depbuilt = !gSystem->Exec(adddictdep); - if (depbuilt) depbuilt = !gSystem->Exec(addversiondep); - - if (!depbuilt) { - ::Warning("ACLiC","Failed to generate the dependency file for %s", + std::ofstream depFile(depfilename, std::ios::out | std::ios::app); + if (!depFile) { + ::Warning("ACLiC", "Failed to open dependency file %s for %s after running rmkdepend", depfilename.Data(), library.Data()); - } else { - if (needToUnlinkTempFile) { - // Remove the temporary stderr file if it was created. - gSystem->Unlink(stderrfile); - } - gSystem->Unlink(bakdepfilename); + return; } + depFile << adddictdep << "\n"; + depFile << libname << version_var_prefix << " \"" << ROOT_RELEASE << "\"\n"; } //////////////////////////////////////////////////////////////////////////////// From 6442c1ce4ad1e033b204e503df3bb61ff8c16130 Mon Sep 17 00:00:00 2001 From: silverweed Date: Fri, 7 Aug 2026 14:01:18 +0200 Subject: [PATCH 8/8] [cmake] Blacklist driveRedirect.py from asan LD_PRELOAD In ROOTTEST_ADD_TEST we have a piece of code that adds the Asan libraries to LD_PRELOAD for python scripts, but it excludes a few special cases. Among these there is driveTabCom.py, which is mentioned explicitly by driveRedirect.py to have a similar functionality (that functionality being driving the root.exe process through a pseudo-interactive tty to test some stuff). For reasons that are not entirely clear to me, these scripts don't want the asan libraries in LD_PRELOAD. Possibly because, not having an `import ROOT`, they don't benefit from the tweaks added by this PR: https://github.com/root-project/root/pull/11621 which prevents Asan libraries from leaking into the ROOT process. This is just a guess. This change fixes a problem with roottest-root-rint-Redirect, which otherwise fails on Alma10 with: ld.so: object '/usr/lib/gcc/x86_64-redhat-linux/14/libasan.so' from LD_PRELOAD cannot be preloaded (file too short): ignored. Notably, this failure doesn't happen on Archlinux. As far as I can tell, the main difference is that on Alma, libasan.so is actually a linker script redirecting to /usr/lib64/libasan.so.8.0.0, whereas in Arch the preloaded library (/usr/lib/libasan.so in that case) is an actual shared object. To be ascertained whether this fix is the "proper" one, but it surely is in line with the way we fixed driveTabCom.py, so if this is to be revised, that one likely needs to be as well. --- cmake/modules/RootMacros.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/modules/RootMacros.cmake b/cmake/modules/RootMacros.cmake index 864f5f6c81a2d..d9139ea0e9ac9 100644 --- a/cmake/modules/RootMacros.cmake +++ b/cmake/modules/RootMacros.cmake @@ -1768,6 +1768,7 @@ function(ROOT_ADD_TEST test) list(FILTER theCommand INCLUDE REGEX "^-DCMD=.*python[0-9.]*[\\^]") if((theCommand AND NOT (_command MATCHES XMLParsing/parseXMLs.py OR + _command MATCHES roottest/root/rint/driveRedirect.py OR _command MATCHES roottest/root/rint/driveTabCom.py)) OR (_command MATCHES roottest/python/cmdLineUtils AND NOT _command MATCHES MakeNameCyclesRootmvInput))