From 6afb8aa5402df60d084604c20030bdd082f6e722 Mon Sep 17 00:00:00 2001 From: pasta Date: Mon, 1 Dec 2025 14:08:01 -0600 Subject: [PATCH 1/8] ci: enable multi-arch Docker image builds for x86 and ARM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for building CI container images for both linux/amd64 and linux/arm64 architectures: - Add QEMU setup and multi-platform support to build-container workflow - Add runs-on input parameter for runner flexibility - Update ci-slim Dockerfile to dynamically select ShellCheck binary based on target architecture 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/build-container.yml | 11 ++++++++++- contrib/containers/ci/ci-slim.Dockerfile | 12 +++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml index 67df008c220d..00b8c696ebc1 100644 --- a/.github/workflows/build-container.yml +++ b/.github/workflows/build-container.yml @@ -15,6 +15,11 @@ on: description: "Container name" required: true type: string + runs-on: + description: "Runner label to use (e.g., ubuntu-24.04 or ubuntu-24.04-arm)" + required: false + default: ubuntu-24.04 + type: string outputs: path: description: "Path to built container" @@ -23,7 +28,7 @@ on: jobs: build: name: Build container - runs-on: ubuntu-24.04 + runs-on: ${{ inputs.runs-on }} outputs: tag: ${{ steps.prepare.outputs.tag }} repo: ${{ steps.prepare.outputs.repo }} @@ -44,6 +49,9 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 + - name: Set up QEMU (for multi-arch emulation) + uses: docker/setup-qemu-action@v3 + - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: @@ -57,6 +65,7 @@ jobs: context: ${{ inputs.context }} file: ${{ inputs.file }} push: true + platforms: linux/amd64,linux/arm64 tags: | ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:${{ hashFiles(inputs.file) }} ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:${{ steps.prepare.outputs.tag }} diff --git a/contrib/containers/ci/ci-slim.Dockerfile b/contrib/containers/ci/ci-slim.Dockerfile index 8aec114ec924..82c5e96f8029 100644 --- a/contrib/containers/ci/ci-slim.Dockerfile +++ b/contrib/containers/ci/ci-slim.Dockerfile @@ -19,6 +19,7 @@ RUN set -ex; \ # Main image FROM ubuntu:noble +ARG TARGETARCH # Include built assets COPY --from=cppcheck-builder /src/cppcheck/build/bin/cppcheck /usr/local/bin/cppcheck @@ -107,7 +108,16 @@ RUN set -ex; \ ARG SHELLCHECK_VERSION=v0.8.0 RUN set -ex; \ - curl -fL "https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" -o /tmp/shellcheck.tar.xz; \ + ARCH_INFERRED="${TARGETARCH}"; \ + if [ -z "${ARCH_INFERRED}" ]; then \ + ARCH_INFERRED="$(dpkg --print-architecture || true)"; \ + fi; \ + case "${ARCH_INFERRED}" in \ + amd64|x86_64) SC_ARCH="x86_64" ;; \ + arm64|aarch64) SC_ARCH="aarch64" ;; \ + *) echo "Unsupported architecture for ShellCheck: ${ARCH_INFERRED}"; exit 1 ;; \ + esac; \ + curl -fL "https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/shellcheck-${SHELLCHECK_VERSION}.linux.${SC_ARCH}.tar.xz" -o /tmp/shellcheck.tar.xz; \ mkdir -p /opt/shellcheck && tar -xf /tmp/shellcheck.tar.xz -C /opt/shellcheck --strip-components=1 && rm /tmp/shellcheck.tar.xz ENV PATH="/opt/shellcheck:${PATH}" From 6b0ed8bd6ea2a7c5d1cd376aaee754b57074944d Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 2 Dec 2025 09:06:05 -0600 Subject: [PATCH 2/8] ci: run multiprocess job exclusively on ARM runners MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add runs-on input parameter to reusable workflow files (build-depends, build-src, test-src) with ubuntu-24.04 as default. Configure only the multiprocess job chain (depends, build, test) to use ubuntu-24.04-arm runners. Include RUNNER_ARCH in depends cache keys to prevent mixing x86 and ARM cached artifacts. Make HOST detection dynamic in 00_setup_env_native_multiprocess.sh to build natively for ARM (aarch64-linux-gnu) when running on ARM runners. Refactor build-container.yml to build each architecture natively: - Build amd64 image on ubuntu-24.04 runner - Build arm64 image on ubuntu-24.04-arm runner - Create multi-arch manifest combining both images This eliminates slow QEMU emulation for cross-arch builds. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/build-container.yml | 108 +++++++++++++++++--- .github/workflows/build-depends.yml | 10 +- .github/workflows/build-src.yml | 7 +- .github/workflows/build.yml | 7 +- .github/workflows/test-src.yml | 7 +- ci/test/00_setup_env_native_multiprocess.sh | 19 +++- ci/test/00_setup_env_native_tsan.sh | 18 ++++ 7 files changed, 153 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml index 00b8c696ebc1..565180305637 100644 --- a/.github/workflows/build-container.yml +++ b/.github/workflows/build-container.yml @@ -15,23 +15,19 @@ on: description: "Container name" required: true type: string - runs-on: - description: "Runner label to use (e.g., ubuntu-24.04 or ubuntu-24.04-arm)" - required: false - default: ubuntu-24.04 - type: string outputs: path: description: "Path to built container" - value: ghcr.io/${{ jobs.build.outputs.repo }}/${{ inputs.name }}:${{ jobs.build.outputs.tag }} + value: ghcr.io/${{ jobs.build-amd64.outputs.repo }}/${{ inputs.name }}:${{ jobs.build-amd64.outputs.tag }} jobs: - build: - name: Build container - runs-on: ${{ inputs.runs-on }} + build-amd64: + name: Build container (amd64) + runs-on: ubuntu-24.04 outputs: tag: ${{ steps.prepare.outputs.tag }} repo: ${{ steps.prepare.outputs.repo }} + digest: ${{ steps.build.outputs.digest }} steps: - name: Checkout code uses: actions/checkout@v4 @@ -49,8 +45,49 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Set up QEMU (for multi-arch emulation) - uses: docker/setup-qemu-action@v3 + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image + id: build + uses: docker/build-push-action@v6 + with: + context: ${{ inputs.context }} + file: ${{ inputs.file }} + push: true + platforms: linux/amd64 + tags: | + ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:${{ hashFiles(inputs.file) }}-amd64 + cache-from: | + type=registry,ref=ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:${{ hashFiles(inputs.file) }}-amd64 + type=registry,ref=ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:${{ steps.prepare.outputs.tag }} + cache-to: type=inline + + build-arm64: + name: Build container (arm64) + runs-on: ubuntu-24.04-arm + outputs: + digest: ${{ steps.build.outputs.digest }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Prepare variables + id: prepare + run: | + BRANCH_NAME=$(echo "${GITHUB_REF##*/}" | tr '[:upper:]' '[:lower:]') + REPO_NAME=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]') + echo "tag=${BRANCH_NAME}" >> $GITHUB_OUTPUT + echo "repo=${REPO_NAME}" >> $GITHUB_OUTPUT + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v3 @@ -60,18 +97,55 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push Docker image + id: build uses: docker/build-push-action@v6 with: context: ${{ inputs.context }} file: ${{ inputs.file }} push: true - platforms: linux/amd64,linux/arm64 + platforms: linux/arm64 tags: | - ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:${{ hashFiles(inputs.file) }} - ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:${{ steps.prepare.outputs.tag }} - ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:latest + ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:${{ hashFiles(inputs.file) }}-arm64 cache-from: | - type=registry,ref=ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:${{ hashFiles(inputs.file) }} + type=registry,ref=ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:${{ hashFiles(inputs.file) }}-arm64 type=registry,ref=ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:${{ steps.prepare.outputs.tag }} - type=registry,ref=ghcr.io/${{ steps.prepare.outputs.repo }}/${{ inputs.name }}:latest cache-to: type=inline + + create-manifest: + name: Create multi-arch manifest + runs-on: ubuntu-24.04-arm + needs: [build-amd64, build-arm64] + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Create and push multi-arch manifest + run: | + REPO="ghcr.io/${{ needs.build-amd64.outputs.repo }}/${{ inputs.name }}" + TAG="${{ needs.build-amd64.outputs.tag }}" + HASH_TAG="${{ hashFiles(inputs.file) }}" + + # Create manifest from arch-specific images + docker buildx imagetools create -t "${REPO}:${HASH_TAG}" \ + "${REPO}:${HASH_TAG}-amd64" \ + "${REPO}:${HASH_TAG}-arm64" + + docker buildx imagetools create -t "${REPO}:${TAG}" \ + "${REPO}:${HASH_TAG}-amd64" \ + "${REPO}:${HASH_TAG}-arm64" + + docker buildx imagetools create -t "${REPO}:latest" \ + "${REPO}:${HASH_TAG}-amd64" \ + "${REPO}:${HASH_TAG}-arm64" diff --git a/.github/workflows/build-depends.yml b/.github/workflows/build-depends.yml index ebd41c079bd0..68c0043bfb4b 100644 --- a/.github/workflows/build-depends.yml +++ b/.github/workflows/build-depends.yml @@ -11,6 +11,11 @@ on: description: "Path to built container at registry" required: true type: string + runs-on: + description: "Runner label to use (e.g., ubuntu-24.04 or ubuntu-24.04-arm)" + required: false + default: ubuntu-24.04 + type: string outputs: key: description: "Key needed for restoring depends cache" @@ -52,11 +57,12 @@ jobs: source ./ci/dash/matrix.sh echo "DEP_OPTS=${DEP_OPTS}" >> "${GITHUB_OUTPUT}" echo "HOST=${HOST}" >> "${GITHUB_OUTPUT}" + echo "RUNNER_ARCH=$(uname -m)" >> "${GITHUB_OUTPUT}" DEP_HASH="$(echo -n "${BUILD_TARGET}" "${DEP_OPTS}" "${HOST}" | sha256sum | head -c 64)" echo "DEP_HASH=${DEP_HASH}" >> "${GITHUB_OUTPUT}" DOCKERFILE_HASH="${{ hashFiles('contrib/containers/ci/ci.Dockerfile', 'contrib/containers/ci/ci-slim.Dockerfile') }}" PACKAGES_HASH="${{ hashFiles('depends/packages/*', 'depends/Makefile') }}" - CACHE_KEY="depends-${DOCKERFILE_HASH}-${{ inputs.build-target }}-${DEP_HASH}-${PACKAGES_HASH}" + CACHE_KEY="depends-${DOCKERFILE_HASH}-${{ inputs.runs-on }}-${{ inputs.build-target }}-${DEP_HASH}-${PACKAGES_HASH}" echo "cache-key=${CACHE_KEY}" >> "${GITHUB_OUTPUT}" echo "Cache key: ${CACHE_KEY}" shell: bash @@ -73,7 +79,7 @@ jobs: name: Build depends needs: [check-cache] if: needs.check-cache.outputs.cache-hit != 'true' - runs-on: ubuntu-24.04 + runs-on: ${{ inputs.runs-on }} container: image: ${{ inputs.container-path }} options: --user root diff --git a/.github/workflows/build-src.yml b/.github/workflows/build-src.yml index 6b1705501fe0..e7f29668ffb9 100644 --- a/.github/workflows/build-src.yml +++ b/.github/workflows/build-src.yml @@ -24,6 +24,11 @@ on: required: false type: string default: "" + runs-on: + description: "Runner label to use (e.g., ubuntu-24.04 or ubuntu-24.04-arm)" + required: false + default: ubuntu-24.04 + type: string outputs: key: description: "Key needed for restoring artifacts bundle" @@ -32,7 +37,7 @@ on: jobs: build-src: name: Build source - runs-on: ubuntu-24.04 + runs-on: ${{ inputs.runs-on }} outputs: key: ${{ steps.bundle.outputs.key }} container: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cd70a4a1e919..0228e46af380 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -86,7 +86,7 @@ jobs: container-path: ${{ needs.container.outputs.path }} depends-linux64_multiprocess: - name: x86_64-pc-linux-gnu_multiprocess + name: linux64_multiprocess uses: ./.github/workflows/build-depends.yml needs: [container, cache-sources] if: | @@ -95,6 +95,7 @@ jobs: with: build-target: linux64_multiprocess container-path: ${{ needs.container.outputs.path }} + runs-on: ubuntu-24.04-arm depends-linux64_nowallet: name: x86_64-pc-linux-gnu_nowallet @@ -176,6 +177,7 @@ jobs: depends-key: ${{ needs.depends-linux64_multiprocess.outputs.key }} depends-host: ${{ needs.depends-linux64_multiprocess.outputs.host }} depends-dep-opts: ${{ needs.depends-linux64_multiprocess.outputs.dep-opts }} + runs-on: ubuntu-24.04-arm src-linux64_nowallet: name: linux64_nowallet-build @@ -211,6 +213,7 @@ jobs: depends-key: ${{ needs.depends-linux64_multiprocess.outputs.key }} depends-host: ${{ needs.depends-linux64_multiprocess.outputs.host }} depends-dep-opts: ${{ needs.depends-linux64_multiprocess.outputs.dep-opts }} + runs-on: ubuntu-24.04-arm src-linux64_ubsan: name: linux64_ubsan-build @@ -263,6 +266,7 @@ jobs: bundle-key: ${{ needs.src-linux64_multiprocess.outputs.key }} build-target: linux64_multiprocess container-path: ${{ needs.container-slim.outputs.path }} + runs-on: ubuntu-24.04-arm test-linux64_nowallet: name: linux64_nowallet-test @@ -290,6 +294,7 @@ jobs: bundle-key: ${{ needs.src-linux64_tsan.outputs.key }} build-target: linux64_tsan container-path: ${{ needs.container-slim.outputs.path }} + runs-on: ubuntu-24.04-arm test-linux64_ubsan: name: linux64_ubsan-test diff --git a/.github/workflows/test-src.yml b/.github/workflows/test-src.yml index c0a9e5e58289..25b213cbe87c 100644 --- a/.github/workflows/test-src.yml +++ b/.github/workflows/test-src.yml @@ -15,6 +15,11 @@ on: description: "Path to built container at registry" required: true type: string + runs-on: + description: "Runner label to use (e.g., ubuntu-24.04 or ubuntu-24.04-arm)" + required: false + default: ubuntu-24.04 + type: string env: INTEGRATION_TESTS_ARGS: "--extended --exclude feature_pruning,feature_dbcrash" @@ -23,7 +28,7 @@ env: jobs: test-src: name: Test source - runs-on: ubuntu-24.04 + runs-on: ${{ inputs.runs-on }} container: image: ${{ inputs.container-path }} options: --user root diff --git a/ci/test/00_setup_env_native_multiprocess.sh b/ci/test/00_setup_env_native_multiprocess.sh index 4583a86737a0..fbb065a1ae95 100755 --- a/ci/test/00_setup_env_native_multiprocess.sh +++ b/ci/test/00_setup_env_native_multiprocess.sh @@ -7,7 +7,24 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_multiprocess -export HOST=x86_64-pc-linux-gnu +case "$(uname -m)" in + aarch64) + export HOST=aarch64-linux-gnu + ;; + x86_64) + export HOST=x86_64-pc-linux-gnu + ;; + *) + if command -v dpkg >/dev/null 2>&1; then + arch="$(dpkg --print-architecture)" + if [ "${arch}" = "arm64" ]; then + export HOST=aarch64-linux-gnu + elif [ "${arch}" = "amd64" ]; then + export HOST=x86_64-pc-linux-gnu + fi + fi + ;; +esac export PACKAGES="cmake python3 llvm clang" export DEP_OPTS="MULTIPROCESS=1 CC=clang-19 CXX=clang++-19" export RUN_TIDY=true diff --git a/ci/test/00_setup_env_native_tsan.sh b/ci/test/00_setup_env_native_tsan.sh index 798ded8afd16..f84f594735f6 100755 --- a/ci/test/00_setup_env_native_tsan.sh +++ b/ci/test/00_setup_env_native_tsan.sh @@ -7,6 +7,24 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_tsan +case "$(uname -m)" in + aarch64) + export HOST=aarch64-linux-gnu + ;; + x86_64) + export HOST=x86_64-pc-linux-gnu + ;; + *) + if command -v dpkg >/dev/null 2>&1; then + arch="$(dpkg --print-architecture)" + if [ "${arch}" = "arm64" ]; then + export HOST=aarch64-linux-gnu + elif [ "${arch}" = "amd64" ]; then + export HOST=x86_64-pc-linux-gnu + fi + fi + ;; +esac export PACKAGES="clang-19 llvm-19 libclang-rt-19-dev libc++abi-19-dev libc++-19-dev python3-zmq" export DEP_OPTS="CC=clang-19 CXX='clang++-19 -stdlib=libc++'" export TEST_RUNNER_EXTRA="--extended --exclude feature_pruning,feature_dbcrash,wallet_multiwallet.py" # Temporarily suppress ASan heap-use-after-free (see issue #14163) From 550e58825b0eea63465a8f71349734064177b78f Mon Sep 17 00:00:00 2001 From: pasta Date: Thu, 4 Dec 2025 18:30:41 -0600 Subject: [PATCH 3/8] test: add TSAN deadlock suppression for BerkeleyBatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BerkeleyDB uses internal pthread rwlocks with its own locking protocol that TSAN cannot properly reason about, causing false positive lock-order-inversion warnings in wallet tests (e.g., ZapSelectTx). The existing deadlock:libdb suppression doesn't match because BDB is statically linked into test_dash. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- test/sanitizer_suppressions/tsan | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan index 77854dd7dc47..a96cfb682ba3 100644 --- a/test/sanitizer_suppressions/tsan +++ b/test/sanitizer_suppressions/tsan @@ -19,6 +19,9 @@ race:bitcoin-qt # https://github.com/bitcoin/bitcoin/issues/19303#issuecomment-1514926359 deadlock:CChainState::ConnectTip deadlock:wallet_tests::CreateWallet +# BerkeleyDB internal lock ordering - BDB uses its own locking protocol +# with pthread rwlocks that TSAN cannot properly reason about +deadlock:BerkeleyBatch # deadlock false positive (see: https://github.com/dashpay/dash/pull/4563) deadlock:CChainState::ConnectTip From 1fa7b64152ce73d451d85f300c2b3b0f54a91737 Mon Sep 17 00:00:00 2001 From: pasta Date: Thu, 4 Dec 2025 19:42:25 -0600 Subject: [PATCH 4/8] test: add TSAN deadlock suppression for DatabaseBatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add suppression for DatabaseBatch alongside BerkeleyBatch to cover BerkeleyDB lock-order-inversion warnings occurring through the DatabaseBatch::Write code path in wallet benchmarks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- test/sanitizer_suppressions/tsan | 1 + 1 file changed, 1 insertion(+) diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan index a96cfb682ba3..dc80031823b6 100644 --- a/test/sanitizer_suppressions/tsan +++ b/test/sanitizer_suppressions/tsan @@ -22,6 +22,7 @@ deadlock:wallet_tests::CreateWallet # BerkeleyDB internal lock ordering - BDB uses its own locking protocol # with pthread rwlocks that TSAN cannot properly reason about deadlock:BerkeleyBatch +deadlock:DatabaseBatch # deadlock false positive (see: https://github.com/dashpay/dash/pull/4563) deadlock:CChainState::ConnectTip From 64d5fb4dcef12b6d8eabb54dc1ec7b554d92aa4a Mon Sep 17 00:00:00 2001 From: pasta Date: Fri, 5 Dec 2025 09:10:19 -0600 Subject: [PATCH 5/8] test: add comprehensive TSAN suppression for BDB pthread mutex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add suppression for __db_pthread_mutex to catch all BerkeleyDB internal pthread rwlock operations. This covers MakeBerkeleyDatabase and any other BDB code paths that trigger lock-order-inversion warnings. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- test/sanitizer_suppressions/tsan | 1 + 1 file changed, 1 insertion(+) diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan index dc80031823b6..d6c32e82d684 100644 --- a/test/sanitizer_suppressions/tsan +++ b/test/sanitizer_suppressions/tsan @@ -23,6 +23,7 @@ deadlock:wallet_tests::CreateWallet # with pthread rwlocks that TSAN cannot properly reason about deadlock:BerkeleyBatch deadlock:DatabaseBatch +deadlock:__db_pthread_mutex # deadlock false positive (see: https://github.com/dashpay/dash/pull/4563) deadlock:CChainState::ConnectTip From 7ef6f3d12ea948b7a48f8f47b560d07c8dba5e92 Mon Sep 17 00:00:00 2001 From: pasta Date: Mon, 8 Dec 2025 13:10:59 -0600 Subject: [PATCH 6/8] chore: move suppressions to "external libraries" --- test/sanitizer_suppressions/tsan | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan index d6c32e82d684..9d9012895b6e 100644 --- a/test/sanitizer_suppressions/tsan +++ b/test/sanitizer_suppressions/tsan @@ -19,11 +19,6 @@ race:bitcoin-qt # https://github.com/bitcoin/bitcoin/issues/19303#issuecomment-1514926359 deadlock:CChainState::ConnectTip deadlock:wallet_tests::CreateWallet -# BerkeleyDB internal lock ordering - BDB uses its own locking protocol -# with pthread rwlocks that TSAN cannot properly reason about -deadlock:BerkeleyBatch -deadlock:DatabaseBatch -deadlock:__db_pthread_mutex # deadlock false positive (see: https://github.com/dashpay/dash/pull/4563) deadlock:CChainState::ConnectTip @@ -46,6 +41,13 @@ race:libzmq # Race in headers only Boost Test race:std::__1::ios_base::flags +# BerkeleyDB internal lock ordering - BDB uses its own locking protocol +# with pthread rwlocks that TSAN cannot properly reason about +deadlock:BerkeleyBatch +deadlock:DatabaseBatch +deadlock:__db_pthread_mutex + + # Intermittent issues # ------------------- # From 72b77f33752b99048444b5fa1598ee28266c4f3b Mon Sep 17 00:00:00 2001 From: pasta Date: Mon, 8 Dec 2025 19:06:53 -0600 Subject: [PATCH 7/8] ci: fix check-cache job to run on correct runner architecture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The check-cache job was hardcoded to run on ubuntu-latest (x86_64), but it computes HOST using uname -m. When the build job runs on ARM (ubuntu-24.04-arm), it received HOST=x86_64-pc-linux-gnu from the cache-check, causing the ARM build to fail trying to compile for x86_64. Fix by using inputs.runs-on for check-cache so HOST detection matches the actual build runner architecture. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/build-depends.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-depends.yml b/.github/workflows/build-depends.yml index 68c0043bfb4b..39c2537e4178 100644 --- a/.github/workflows/build-depends.yml +++ b/.github/workflows/build-depends.yml @@ -30,7 +30,7 @@ on: jobs: check-cache: name: Check cache - runs-on: ubuntu-latest + runs-on: ${{ inputs.runs-on }} outputs: cache-hit: ${{ steps.cache-check.outputs.cache-hit }} cache-key: ${{ steps.setup.outputs.cache-key }} From ecbce3216efa8ff45f3087cc413c841115fc8eaa Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 23 Dec 2025 08:20:31 -0600 Subject: [PATCH 8/8] fix: resolve quotes --- .github/workflows/build-container.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml index 565180305637..94ef347fbe1e 100644 --- a/.github/workflows/build-container.yml +++ b/.github/workflows/build-container.yml @@ -39,8 +39,8 @@ jobs: run: | BRANCH_NAME=$(echo "${GITHUB_REF##*/}" | tr '[:upper:]' '[:lower:]') REPO_NAME=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]') - echo "tag=${BRANCH_NAME}" >> $GITHUB_OUTPUT - echo "repo=${REPO_NAME}" >> $GITHUB_OUTPUT + echo "tag=${BRANCH_NAME}" >> "$GITHUB_OUTPUT" + echo "repo=${REPO_NAME}" >> "$GITHUB_OUTPUT" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -83,8 +83,8 @@ jobs: run: | BRANCH_NAME=$(echo "${GITHUB_REF##*/}" | tr '[:upper:]' '[:lower:]') REPO_NAME=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]') - echo "tag=${BRANCH_NAME}" >> $GITHUB_OUTPUT - echo "repo=${REPO_NAME}" >> $GITHUB_OUTPUT + echo "tag=${BRANCH_NAME}" >> "$GITHUB_OUTPUT" + echo "repo=${REPO_NAME}" >> "$GITHUB_OUTPUT" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3