Skip to content

Commit f404dfb

Browse files
committed
ci(msan): retry transient network failures while building the MSan image
The test-msan lane dies whenever the buildx layer cache misses and the builder's resolver hiccups. PR-CI runs 33816056229 and 33818108315 both failed in "Build MSan image (cached layers)" with: #7 26.77 Could not resolve 'apt.llvm.org' #7 27.34 W: Failed to fetch http://apt.llvm.org/noble/dists/\ llvm-toolchain-noble-22/InRelease Could not resolve 'apt.llvm.org' ERROR: failed to build: failed to solve: process "/bin/sh -c apt-get \ update && ..." did not complete successfully The wget of the signing key from that SAME host had succeeded seconds earlier in the same layer, so this is a transient DNS failure inside buildkit, not a wrong URL or a dead mirror. 2 of the last 15 PR runs. Every network-touching step in Dockerfile.msan now runs under a small POSIX-sh helper written into the image before the first layer that needs it: /usr/local/bin/retry makes 5 attempts with growing backoff (5s/10s/20s/40s) and still exits non-zero once they are exhausted, so a genuine breakage keeps failing the build instead of being swallowed. Wrapped: both apt-get update/install pairs (also given -o Acquire::Retries=3), the wget of the LLVM signing key, and the llvm-project and zlib clones. Two shapes needed care: - the key is fetched with `wget -O <file>` instead of `-qO- > <file>`, because a redirect is opened once for all attempts and a partial write from a failed attempt would be prepended to a later successful one; - each clone clears its destination first, or a half-finished clone makes every later attempt fail on "destination path already exists". The pinned base digest, the pinned llvmorg-22.1.0 / v1.3.1 tags, --no-install-recommends and the layer structure are unchanged; on a healthy network the image is byte-for-byte the same work as before. Verified on Colima: - `docker buildx build --check -f test-infrastructure/Dockerfile.msan test-infrastructure/` -> "Check complete, no warnings found." - scratch image = FROM + helper + the real apt.llvm.org layer, built --no-cache: layer completes, clang-22/llvm-22 installed. - scratch image where the wrapped command fails twice then succeeds: attempts 1 and 2 logged with 5s/10s backoff, attempt 3 succeeds, build exit 0. - scratch image where the wrapped command always fails: 5 attempts, "retry: giving up after 5 attempts", retry_exit=1, build exit 1. The full MSan image was deliberately not built locally (it compiles libc++ with MSan); CI builds it on the branch. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
1 parent 8f64c36 commit f404dfb

1 file changed

Lines changed: 38 additions & 8 deletions

File tree

‎test-infrastructure/Dockerfile.msan‎

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,47 @@
1616
# Same pinned base as the primary test image — bump deliberately, never to a tag.
1717
FROM ubuntu:noble@sha256:4fbb8e6a8395de5a7550b33509421a2bafbc0aab6c06ba2cef9ebffbc7092d90
1818

19+
# WHY every network step below is wrapped: on a cache miss the builder's
20+
# resolver hiccups and takes the whole lane down. PR-CI runs 33816056229 and
21+
# 33818108315 both died with `Could not resolve 'apt.llvm.org'` inside the
22+
# clang layer — seconds AFTER a wget from that same host had succeeded in the
23+
# same layer, i.e. a transient buildkit-side DNS failure, not a wrong URL.
24+
# retry: 5 attempts with growing backoff, and it still exits non-zero after
25+
# the last one, so a genuine breakage keeps failing the build.
26+
RUN printf '%s\n' \
27+
'#!/bin/sh' \
28+
'# retry <cmd> [args...]: 5 attempts, sleeping 5s/10s/20s/40s between them.' \
29+
'attempt=1; delay=5' \
30+
'until "$@"; do' \
31+
' if [ "$attempt" -ge 5 ]; then' \
32+
' echo "retry: giving up after $attempt attempts: $*" >&2' \
33+
' exit 1' \
34+
' fi' \
35+
' echo "retry: attempt $attempt failed, sleeping ${delay}s before retrying: $*" >&2' \
36+
' sleep "$delay"' \
37+
' attempt=$((attempt + 1)); delay=$((delay * 2))' \
38+
'done' \
39+
> /usr/local/bin/retry \
40+
&& chmod 0755 /usr/local/bin/retry
41+
1942
# clang 22 from apt.llvm.org, matching the diag and analyzer lanes. Noble's
2043
# default is clang 18 — four majors behind everything else here, which is both
2144
# an inconsistency and a bad vantage point for debugging sanitizer behaviour.
22-
RUN apt-get update && apt-get install -y --no-install-recommends wget gnupg ca-certificates \
23-
&& wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key > /etc/apt/trusted.gpg.d/apt.llvm.org.asc \
45+
# The key is fetched with `wget -O <file>` rather than `-qO- > <file>`: under
46+
# retry a redirect is opened once for all attempts, so a partial write from a
47+
# failed attempt would be prepended to the output of a later successful one.
48+
RUN retry apt-get -o Acquire::Retries=3 update \
49+
&& retry apt-get -o Acquire::Retries=3 install -y --no-install-recommends wget gnupg ca-certificates \
50+
&& retry wget -q -O /etc/apt/trusted.gpg.d/apt.llvm.org.asc https://apt.llvm.org/llvm-snapshot.gpg.key \
2451
&& echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-22 main" > /etc/apt/sources.list.d/llvm-22.list \
25-
&& apt-get update && apt-get install -y --no-install-recommends \
52+
&& retry apt-get -o Acquire::Retries=3 update \
53+
&& retry apt-get -o Acquire::Retries=3 install -y --no-install-recommends \
2654
clang-22 libclang-rt-22-dev llvm-22 \
2755
&& ln -sf /usr/bin/clang-22 /usr/bin/clang \
2856
&& ln -sf /usr/bin/clang++-22 /usr/bin/clang++
2957

30-
RUN apt-get update && apt-get install -y --no-install-recommends \
58+
RUN retry apt-get -o Acquire::Retries=3 update \
59+
&& retry apt-get -o Acquire::Retries=3 install -y --no-install-recommends \
3160
cmake \
3261
ninja-build \
3362
make \
@@ -40,9 +69,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
4069
&& rm -rf /var/lib/apt/lists/*
4170

4271
# libc++ + libc++abi + libunwind with MemoryWithOrigins, at the SAME major as
43-
# the compiler above — a runtimes build must match its clang.
44-
RUN git clone --depth 1 --branch llvmorg-22.1.0 \
45-
https://github.com/llvm/llvm-project.git /tmp/llvm-project \
72+
# the compiler above — a runtimes build must match its clang. The clone clears
73+
# its destination first: a half-finished clone would make every later attempt
74+
# fail on "destination path already exists".
75+
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' \
4676
&& cmake -G Ninja -S /tmp/llvm-project/runtimes -B /tmp/llvm-msan \
4777
-DCMAKE_BUILD_TYPE=Release \
4878
-DCMAKE_C_COMPILER=clang \
@@ -59,7 +89,7 @@ RUN git clone --depth 1 --branch llvmorg-22.1.0 \
5989
&& rm -rf /tmp/llvm-project /tmp/llvm-msan
6090

6191
# zlib with MSan (static, so the runner needs no runtime path for it).
62-
RUN git clone --depth 1 --branch v1.3.1 https://github.com/madler/zlib.git /tmp/zlib \
92+
RUN retry sh -c 'rm -rf /tmp/zlib && git clone --depth 1 --branch v1.3.1 https://github.com/madler/zlib.git /tmp/zlib' \
6393
&& cd /tmp/zlib \
6494
&& CC=clang CFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -O2" \
6595
./configure --prefix=/opt/msan --static \

0 commit comments

Comments
 (0)