Skip to content

Framework: fix omitting _asan_ by CTEST_BUILD_NAME#15176

Open
ViNN280801 wants to merge 1 commit intotrilinos:developfrom
ViNN280801:framework/ctest-asan-route-genconfig
Open

Framework: fix omitting _asan_ by CTEST_BUILD_NAME#15176
ViNN280801 wants to merge 1 commit intotrilinos:developfrom
ViNN280801:framework/ctest-asan-route-genconfig

Conversation

@ViNN280801
Copy link
Copy Markdown
Contributor

@trilinos/framework

Motivation

Proposed fix: treat the build as ASAN for the CTest memcheck branch if either CTEST_BUILD_NAME or genconfig_build_name.txt matches .*_asan_.* (see ctest-stage-test.cmake).

Why this can matter: CTEST_BUILD_NAME may follow dashboard_build_name and omit _asan_ while GenConfig still selects ASAN (TrilinosPRConfigurationBase.py, pullrequest_build_name). The old test step only checked CTEST_BUILD_NAME. Then the memcheck branch could be skipped while genconfig_build_name.txt (written in ctest-cdash-setup.cmake from GENCONFIG_BUILD_NAME) still reflects an ASAN GenConfig name. The fix reads that file so the two sources cannot disagree silently.

References

Analyzing #15171 suggested an idea.

Testing

Testing represented as a simple bash script with copy of cmake snippet from actual changes:

#!/usr/bin/env bash
# Legacy: only CTEST_BUILD_NAME matches .*_asan_.*
# Current: same + genconfig_build_name.txt (logic mirrors ctest-stage-test.cmake macro)
set -euo pipefail

td="$(mktemp -d)"
trap 'rm -rf "$td"' EXIT
mkdir -p "$td/b"

gc_asan='rhel_clang-openmpi_debug_shared_no-kokkos-arch_asan_no-complex_no-fpic_mpi_no-pt_no-rdc_no-uvm_deprecated-on_all'
gc_noasan='rhel_clang-openmpi_debug_shared_no-kokkos-arch_no-asan_no-complex_no-fpic_mpi_no-pt_no-rdc_no-uvm_deprecated-on_all'
dash='container_20251204_debug_shared_address-sanitizer'
pr='PR-1-test-rhel_clang-openmpi_debug_shared_no-kokkos-arch_asan_x-1'

legacy="$td/legacy.cmake"
cat >"$legacy" <<'EOF'
if(NOT DEFINED CTEST_BUILD_NAME)
  message(FATAL_ERROR "CTEST_BUILD_NAME")
endif()
set(_v FALSE)
if(CTEST_BUILD_NAME MATCHES ".*_asan_.*")
  set(_v TRUE)
endif()
message("legacy_use_asan_memcheck=${_v}")
EOF

check="$td/check.cmake"
cat >"$check" <<'EOF'
if(NOT DEFINED CTEST_BINARY_DIRECTORY)
  message(FATAL_ERROR "CTEST_BINARY_DIRECTORY")
endif()
if(NOT DEFINED CTEST_BUILD_NAME)
  message(FATAL_ERROR "CTEST_BUILD_NAME")
endif()
set(TRILINOS_CTEST_USE_ASAN_MEMCHECK FALSE)
set(TRILINOS_CTEST_USE_ASAN_MEMCHECK_REASON "")
if(CTEST_BUILD_NAME MATCHES ".*_asan_.*")
  set(TRILINOS_CTEST_USE_ASAN_MEMCHECK TRUE)
  set(TRILINOS_CTEST_USE_ASAN_MEMCHECK_REASON "CTEST_BUILD_NAME matches .*_asan_.*")
endif()
set(_f "${CTEST_BINARY_DIRECTORY}/genconfig_build_name.txt")
if(EXISTS "${_f}")
  file(READ "${_f}" _c)
  string(STRIP "${_c}" _c)
  if(_c MATCHES ".*_asan_.*")
    set(TRILINOS_CTEST_USE_ASAN_MEMCHECK TRUE)
    if(TRILINOS_CTEST_USE_ASAN_MEMCHECK_REASON STREQUAL "")
      set(TRILINOS_CTEST_USE_ASAN_MEMCHECK_REASON "genconfig_build_name.txt matches .*_asan_.*")
    else()
      set(TRILINOS_CTEST_USE_ASAN_MEMCHECK_REASON "${TRILINOS_CTEST_USE_ASAN_MEMCHECK_REASON}; genconfig_build_name.txt matches .*_asan_.*")
    endif()
  endif()
endif()
message("use=${TRILINOS_CTEST_USE_ASAN_MEMCHECK} reason=${TRILINOS_CTEST_USE_ASAN_MEMCHECK_REASON}")
EOF

printf '%s\n' "1 legacy dash+genconfig(_asan_)"
printf '%s\n' "$gc_asan" >"$td/b/genconfig_build_name.txt"
cmake -DCTEST_BUILD_NAME="$dash" -P "$legacy"

printf '%s\n' "2 route dash+genconfig(_asan_)"
cmake -DCTEST_BINARY_DIRECTORY="$td/b" -DCTEST_BUILD_NAME="$dash" -P "$check"

printf '%s\n' "3 route dash+genconfig(no-asan)"
printf '%s\n' "$gc_noasan" >"$td/b/genconfig_build_name.txt"
cmake -DCTEST_BINARY_DIRECTORY="$td/b" -DCTEST_BUILD_NAME="$dash" -P "$check"

printf '%s\n' "4 route prname(_asan_)+no genconfig file"
rm -f "$td/b/genconfig_build_name.txt"
cmake -DCTEST_BINARY_DIRECTORY="$td/b" -DCTEST_BUILD_NAME="$pr" -P "$check"

Output:

1 legacy dash+genconfig(_asan_)
legacy_use_asan_memcheck=FALSE
2 route dash+genconfig(_asan_)
use=TRUE reason=genconfig_build_name.txt matches .*_asan_.*
3 route dash+genconfig(no-asan)
use=FALSE reason=
4 route prname(_asan_)+no genconfig file
use=TRUE reason=CTEST_BUILD_NAME matches .*_asan_.*

… is set. Also see genconfig_build_name.txt for .*_asan_.* so LSAN_OPTIONS and ctest_memcheck match the GenConfig ASAN build

Signed-off-by: ViNN280801 <vladislav.semykin@gmail.com>
@github-actions
Copy link
Copy Markdown

CDash for AT2 results [Currently only accessible from Sandia networks]

Reproducing CI builds locally

CI builds can be reproduced locally in a container.

Requirements: Python 3.9+, Podman, CMake

Steps:

  • Check out the branch of the PR locally.
  • Run commonTools/pr_reproducer/reproducer.sh.

@sebrowne
Copy link
Copy Markdown
Contributor

This is a good catch, I missed that it wasn't running the ctest_memcheck() phase. I'd prefer to explicitly turn the memcheck on or off based on the value of the GenConfig build ID (which we know in the Python-based driver scripts). I'll submit a PR tomorrow morning.

@ViNN280801
Copy link
Copy Markdown
Contributor Author

@sebrowne, got it. I actually have the fix ready on the CMake side. if you point me to the right place in the Python scripts, I can update this PR to do it that way. Otherwise, I'll stand by for your PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants