mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
fix(release): build musl targets via cargo-zigbuild to fix arm64 SIGSEGV
The shipped aarch64-unknown-linux-musl binary segfaulted at startup on every arm64 runtime (Apple Silicon, Graviton, Ampere, Docker arm64). Root cause: a glibc-vs-musl .init_array calling-convention mismatch -- a C static library in the dep graph has an __attribute__((constructor)) that expects (argc, argv, envp) per glibc, but musl on aarch64 calls it with no args, so register garbage propagates into pointer arithmetic and faults before main runs. Switch the musl compile steps to cargo-zigbuild (zig 0.13.0). Zig's bundled cc + lld produce working static-PIE binaries for both musl targets, sidestepping Ubuntu musl-tools' -no-pie quirk and the init_array ordering that triggered the crash. Drop the CARGO_TARGET_* linker overrides and the musl-tools apt install -- zig handles both. bin/dev/docker-build.sh mirrors the same toolchain so the local Docker image build matches CI. Verified by running fabro version from the resulting arm64 image on ghcr.io/fabro-sh/dhi-alpine-base:3.23-dev, alpine:3.22, and debian:stable-slim -- all print the version banner with exit 0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
13f612b111
commit
8da81fdf9e
3 changed files with 43 additions and 25 deletions
32
.github/workflows/release.yml
vendored
32
.github/workflows/release.yml
vendored
|
|
@ -54,10 +54,6 @@ jobs:
|
|||
runner: ubuntu-24.04-arm-32-cores
|
||||
musl: true
|
||||
env:
|
||||
CC_x86_64_unknown_linux_musl: musl-gcc
|
||||
CC_aarch64_unknown_linux_musl: musl-gcc
|
||||
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER: musl-gcc
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER: musl-gcc
|
||||
LIBZ_SYS_STATIC: "1"
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
|
@ -70,26 +66,38 @@ jobs:
|
|||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential pkg-config libssl-dev
|
||||
|
||||
- name: Install musl toolchain
|
||||
if: matrix.musl
|
||||
run: sudo apt-get install -y musl-tools
|
||||
|
||||
- name: Set up Rust
|
||||
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Set up zig
|
||||
if: matrix.musl
|
||||
uses: mlugg/setup-zig@8d6198c65fb0feaa111df26e6b467fea8345e46f # v2.0.5
|
||||
with:
|
||||
version: 0.13.0
|
||||
|
||||
- name: Install cargo-zigbuild
|
||||
if: matrix.musl
|
||||
uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # v2
|
||||
with:
|
||||
tool: cargo-zigbuild
|
||||
|
||||
- uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # nextest
|
||||
|
||||
- name: Test
|
||||
# aarch64-musl binaries SIGSEGV at startup when launched on the
|
||||
# ubuntu-24.04-arm runner (glibc host + retrofitted musl loader).
|
||||
# The shipped binary targets Alpine via the Docker image, which
|
||||
# runs natively. x86_64-musl tests still run for coverage.
|
||||
# aarch64-musl test runs have not been validated on the compile
|
||||
# runner yet; shipping binary is exercised via Docker smoke tests.
|
||||
# Re-enable after verifying the workspace passes on this target.
|
||||
if: matrix.target != 'aarch64-unknown-linux-musl'
|
||||
run: cargo nextest run --workspace --target ${{ matrix.target }} --release --status-level slow --profile ci
|
||||
|
||||
- name: Build (musl via cargo-zigbuild)
|
||||
if: matrix.musl
|
||||
run: cargo zigbuild --target ${{ matrix.target }} --release -p fabro-cli
|
||||
|
||||
- name: Build
|
||||
if: ${{ !matrix.musl }}
|
||||
run: cargo build --target ${{ matrix.target }} --release -p fabro-cli
|
||||
|
||||
- name: Package
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@
|
|||
# Build a local fabro Docker image from the current working tree.
|
||||
#
|
||||
# The Docker image uses musl binaries for a small Alpine-based runtime. We
|
||||
# compile fabro-cli for the target musl triple inside rust:1-bookworm so the
|
||||
# binary matches what the Alpine runtime expects, regardless of host OS.
|
||||
# Cargo registry and target dir are cached in named volumes so subsequent
|
||||
# runs are incremental.
|
||||
# compile fabro-cli for the target musl triple inside rust:1-bookworm using
|
||||
# cargo-zigbuild (zig as the C compiler + linker). Cargo registry and target
|
||||
# dir are cached in named volumes so subsequent runs are incremental.
|
||||
#
|
||||
# Usage:
|
||||
# bin/dev/docker-build.sh # host arch, build image at end
|
||||
|
|
@ -46,26 +45,36 @@ if [ -z "$arch" ]; then
|
|||
fi
|
||||
|
||||
case "$arch" in
|
||||
amd64) target=x86_64-unknown-linux-musl cc_var=CC_x86_64_unknown_linux_musl linker_var=CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER ;;
|
||||
arm64) target=aarch64-unknown-linux-musl cc_var=CC_aarch64_unknown_linux_musl linker_var=CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER ;;
|
||||
amd64) target=x86_64-unknown-linux-musl zig_arch=x86_64 ;;
|
||||
arm64) target=aarch64-unknown-linux-musl zig_arch=aarch64 ;;
|
||||
*) echo "unsupported arch: $arch (expected amd64 or arm64)" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
echo "Building fabro-cli for $target inside rust:1-bookworm..."
|
||||
ZIG_VERSION=0.13.0
|
||||
|
||||
echo "Building fabro-cli for $target inside rust:1-bookworm via cargo-zigbuild..."
|
||||
docker run --rm --platform "linux/$arch" \
|
||||
-v "$PWD:/src" \
|
||||
-v fabro-docker-cargo-registry:/usr/local/cargo/registry \
|
||||
-v "fabro-docker-cargo-target-$arch:/target" \
|
||||
-v "fabro-docker-zig-$arch:/opt/zig" \
|
||||
-v "fabro-docker-cargo-tools-$arch:/opt/cargo-tools" \
|
||||
-w /src \
|
||||
-e CARGO_TARGET_DIR=/target \
|
||||
-e "$cc_var=musl-gcc" \
|
||||
-e "$linker_var=musl-gcc" \
|
||||
-e LIBZ_SYS_STATIC=1 \
|
||||
rust:1-bookworm \
|
||||
sh -c "
|
||||
apt-get update -qq && apt-get install -y -qq musl-tools pkg-config perl make >/dev/null &&
|
||||
rustup target add $target &&
|
||||
cargo build --release -p fabro-cli --target $target
|
||||
bash -c "
|
||||
set -e
|
||||
apt-get update -qq && apt-get install -y -qq pkg-config perl make cmake xz-utils curl >/dev/null
|
||||
if [ ! -x /opt/zig/zig-linux-$zig_arch-$ZIG_VERSION/zig ]; then
|
||||
curl -fsSL https://ziglang.org/download/$ZIG_VERSION/zig-linux-$zig_arch-$ZIG_VERSION.tar.xz | tar -xJ -C /opt/zig
|
||||
fi
|
||||
export PATH=/opt/cargo-tools/bin:/opt/zig/zig-linux-$zig_arch-$ZIG_VERSION:\$PATH
|
||||
if ! command -v cargo-zigbuild >/dev/null; then
|
||||
cargo install --locked --root /opt/cargo-tools cargo-zigbuild
|
||||
fi
|
||||
rustup target add $target
|
||||
cargo zigbuild --release -p fabro-cli --target $target
|
||||
"
|
||||
|
||||
echo "Extracting binary from builder cache..."
|
||||
|
|
|
|||
|
|
@ -25,4 +25,5 @@ A new `docker-compose.prod.yaml` stands up a Caddy 2 sidecar that handles auto-H
|
|||
- Fixed Gemini API keys being sent as URL query parameters; they now go through the `x-goog-api-key` header so they don't leak into access logs, proxies, or request traces
|
||||
- Hardened the `fabro-demo` cookie with `HttpOnly` unconditionally and `Secure` when the web URL is HTTPS
|
||||
- Fixed a path-traversal issue where authenticated users could send percent-encoded `..` segments in the GitHub repo lookup endpoint and redirect the server's privileged token to an unintended GitHub API path; owner and repo now require `[A-Za-z0-9._-]` with length caps
|
||||
- Fixed SIGSEGV at startup on the `aarch64-unknown-linux-musl` target (Apple Silicon, Graviton, Ampere) caused by a glibc-vs-musl `.init_array` calling-convention mismatch; the release pipeline now uses `cargo-zigbuild` for musl targets, producing binaries that start cleanly on arm64 Alpine, Debian, and DHI runtimes
|
||||
</Accordion>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue