Skip to content

restate-server 1.7.x arm64 builds crash with SIGILL on ARMv8.0 CPUs (LSE atomics inlined) #5123

Description

@kevinwmerritt

Summary

Starting with 1.7.0, the arm64 container images (and, by extension, the aarch64-unknown-linux-musl builds) crash immediately with SIGILL (exit code 132) on ARMv8.0-A CPUs. 1.6.2 runs fine on the same host.

The binary appears to be compiled with LSE atomics (ARMv8.1-A) inlined unconditionally, rather than going through the runtime-dispatched outline-atomics helpers that 1.6.2 used.

There is no error message — the process dies before it can log anything, which makes this fairly hard to diagnose from the outside.

Environment

  • Host: Raspberry Pi 4 Model B Rev 1.5 (Cortex-A72, ARMv8.0-A)
  • Kernel: Linux 6.1.21-v8+, aarch64
  • Docker image: docker.restate.dev/restatedev/restate (.Architecture = arm64, .Os = linux)
  • /proc/cpuinfo features: fp asimd evtstrm crc32 cpuid — note the absence of atomics (LSE)

Reproduction

$ docker run --rm --entrypoint /bin/sh docker.restate.dev/restatedev/restate:1.7.2 -c "restate-server --version"
Illegal instruction (core dumped)

Under docker compose, this shows up as a restart loop with no log output at all:

NAME      IMAGE                                         STATUS
restate   docker.restate.dev/restatedev/restate:1.7.2   Restarting (132) 2 seconds ago

Affected versions

Every 1.7.x release fails; 1.6.2 is fine:

Version Result
1.6.2 restate-server 1.6.2
1.7.0 Illegal instruction (core dumped)
1.7.1 Illegal instruction (core dumped)
1.7.2 Illegal instruction (core dumped)

Evidence

Disassembling /usr/local/bin/restate-server from each image (objdump -d) and counting LSE atomic instructions (cas*, ldadd*, ldclr*, ldeor*, ldset*, swp*) versus the outline-atomics helper symbols (__aarch64_cas4_relax, __aarch64_ldadd4_acq_rel, …):

LSE instructions __aarch64_* outline-atomics symbols
1.6.2 28 46
1.7.2 ~150,000 22

Breakdown of the most common LSE instructions in 1.7.2:

  97056 ldaddl
  26594 ldadd
   5381 ldaddal
   5083 casal
   2728 swpl
   2294 casa
   2230 casl
   ...

In 1.6.2 the handful of LSE instructions live inside the compiler-rt outline-atomics helpers, which dispatch at runtime on HWCAP_ATOMICS and fall back to ldxr/stxr — so the binary runs correctly on ARMv8.0. In 1.7.2 they are inlined directly throughout the binary, so any ARMv8.0 CPU takes SIGILL on the first one executed.

This looks like an unintentional change to the arm64 build target (e.g. a -C target-cpu= / target-feature=+lse setting, or a toolchain default change), rather than a deliberate raise of the minimum supported CPU.

Impact

This silently drops support for all ARMv8.0-A hardware, which includes Raspberry Pi 4 / CM4, and various older ARM SBCs and NAS devices. Because the process dies with no output whatsoever, the failure mode is quite opaque — a docker compose pull on a :latest tag turns a working deployment into a silent restart loop.

Suggested resolution

Either of:

  1. Restore ARMv8.0 compatibility by building the release artifacts with outline-atomics enabled (the Rust outline-atomics target feature, which is the default for aarch64-unknown-linux-* unless overridden) and without an elevated target-cpu. This keeps LSE performance on capable hardware via runtime dispatch.
  2. If the raise is intentional, please document the minimum supported ARM baseline in the release notes and installation docs — the download tables currently just say "ARM64 MUSL Linux", and a clear startup error would be much friendlier than a bare SIGILL.

Happy to run further diagnostics on this hardware if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions