diff --git a/test-infrastructure/Dockerfile.msan b/test-infrastructure/Dockerfile.msan index d9d9aa3c3..e2867c88a 100644 --- a/test-infrastructure/Dockerfile.msan +++ b/test-infrastructure/Dockerfile.msan @@ -16,18 +16,47 @@ # Same pinned base as the primary test image — bump deliberately, never to a tag. FROM ubuntu:noble@sha256:4fbb8e6a8395de5a7550b33509421a2bafbc0aab6c06ba2cef9ebffbc7092d90 +# WHY every network step below is wrapped: on a cache miss the builder's +# resolver hiccups and takes the whole lane down. PR-CI runs 33816056229 and +# 33818108315 both died with `Could not resolve 'apt.llvm.org'` inside the +# clang layer — seconds AFTER a wget from that same host had succeeded in the +# same layer, i.e. a transient buildkit-side DNS failure, not a wrong URL. +# retry: 5 attempts with growing backoff, and it still exits non-zero after +# the last one, so a genuine breakage keeps failing the build. +RUN printf '%s\n' \ + '#!/bin/sh' \ + '# retry [args...]: 5 attempts, sleeping 5s/10s/20s/40s between them.' \ + 'attempt=1; delay=5' \ + 'until "$@"; do' \ + ' if [ "$attempt" -ge 5 ]; then' \ + ' echo "retry: giving up after $attempt attempts: $*" >&2' \ + ' exit 1' \ + ' fi' \ + ' echo "retry: attempt $attempt failed, sleeping ${delay}s before retrying: $*" >&2' \ + ' sleep "$delay"' \ + ' attempt=$((attempt + 1)); delay=$((delay * 2))' \ + 'done' \ + > /usr/local/bin/retry \ + && chmod 0755 /usr/local/bin/retry + # clang 22 from apt.llvm.org, matching the diag and analyzer lanes. Noble's # default is clang 18 — four majors behind everything else here, which is both # an inconsistency and a bad vantage point for debugging sanitizer behaviour. -RUN apt-get update && apt-get install -y --no-install-recommends wget gnupg ca-certificates \ - && wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key > /etc/apt/trusted.gpg.d/apt.llvm.org.asc \ +# The key is fetched with `wget -O ` rather than `-qO- > `: under +# retry a redirect is opened once for all attempts, so a partial write from a +# failed attempt would be prepended to the output of a later successful one. +RUN retry apt-get -o Acquire::Retries=3 update \ + && retry apt-get -o Acquire::Retries=3 install -y --no-install-recommends wget gnupg ca-certificates \ + && retry wget -q -O /etc/apt/trusted.gpg.d/apt.llvm.org.asc https://apt.llvm.org/llvm-snapshot.gpg.key \ && echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-22 main" > /etc/apt/sources.list.d/llvm-22.list \ - && apt-get update && apt-get install -y --no-install-recommends \ + && retry apt-get -o Acquire::Retries=3 update \ + && retry apt-get -o Acquire::Retries=3 install -y --no-install-recommends \ clang-22 libclang-rt-22-dev llvm-22 \ && ln -sf /usr/bin/clang-22 /usr/bin/clang \ && ln -sf /usr/bin/clang++-22 /usr/bin/clang++ -RUN apt-get update && apt-get install -y --no-install-recommends \ +RUN retry apt-get -o Acquire::Retries=3 update \ + && retry apt-get -o Acquire::Retries=3 install -y --no-install-recommends \ cmake \ ninja-build \ make \ @@ -40,9 +69,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* # libc++ + libc++abi + libunwind with MemoryWithOrigins, at the SAME major as -# the compiler above — a runtimes build must match its clang. -RUN git clone --depth 1 --branch llvmorg-22.1.0 \ - https://github.com/llvm/llvm-project.git /tmp/llvm-project \ +# the compiler above — a runtimes build must match its clang. The clone clears +# its destination first: a half-finished clone would make every later attempt +# fail on "destination path already exists". +RUN retry sh -c 'rm -rf /tmp/llvm-project && git clone --depth 1 --branch llvmorg-22.1.0 https://github.com/llvm/llvm-project.git /tmp/llvm-project' \ && cmake -G Ninja -S /tmp/llvm-project/runtimes -B /tmp/llvm-msan \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_COMPILER=clang \ @@ -59,7 +89,7 @@ RUN git clone --depth 1 --branch llvmorg-22.1.0 \ && rm -rf /tmp/llvm-project /tmp/llvm-msan # zlib with MSan (static, so the runner needs no runtime path for it). -RUN git clone --depth 1 --branch v1.3.1 https://github.com/madler/zlib.git /tmp/zlib \ +RUN retry sh -c 'rm -rf /tmp/zlib && git clone --depth 1 --branch v1.3.1 https://github.com/madler/zlib.git /tmp/zlib' \ && cd /tmp/zlib \ && CC=clang CFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -O2" \ ./configure --prefix=/opt/msan --static \