Skip to content

build: reject prebuilt baseline macOS builds (no Nehalem macOS WebKit) - #32512

Closed
robobun wants to merge 3 commits into
mainfrom
farm/0c5dad80/reject-prebuilt-baseline-macos
Closed

robobun wants to merge 3 commits into
mainfrom
farm/0c5dad80/reject-prebuilt-baseline-macos

Conversation

@robobun

@robobun robobun commented Jun 19, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The released bun-darwin-x64-baseline binary crashes with SIGILL (illegal instruction) at launch on pre-Haswell Intel Macs (Ivy Bridge, real MacPro6,1, and OCLP setups). The "baseline" macOS x64 binary is not actually baseline: it links the Haswell macOS WebKit prebuilt, which contains BMI2/AVX2 instructions that Ivy Bridge cannot decode.

Addresses #32511 and #26872 (same root cause: the shipped bun-darwin-x64-baseline SIGILLs on no-AVX2 / pre-Haswell Intel Macs). Not auto-closing either: this stops Bun from building and shipping a macOS binary mislabeled as "baseline", but a binary that actually runs on those CPUs additionally needs a Nehalem macOS WebKit built in oven-sh/WebKit (cross-repo, see below).

Root cause

The crash fires in a C++ static initializer at process startup (dyld4::Loader::findAndRunAllInitializers in the backtrace), before main() runs. The faulting bytes from the crash report are c4 e2 f1 f7 d0, which decode to the BMI2 instruction shlx (Haswell, 2013+). Ivy Bridge has AVX1 but no BMI1/BMI2, so the CPU raises SIGILL.

Disassembling the shipped v1.3.14 bun-darwin-x64-baseline at the crash offset (0x880A4A) confirms it byte-for-byte:

100880a45: mov    eax,0x1
100880a4a: shlx   rdx,rax,rcx          <== CRASH (BMI2)
100880a4f: mov    rsi,0xffffffffffff0000
100880a64: shlx   rax,rax,rdx          (BMI2)
100880a81: blsr   rdx,rcx              (BMI1)

This is a power-of-two size-class computation in a memory allocator's global constructor, i.e. WebKit's bmalloc setting up its size-class tables at startup.

Bun's own code is built correctly for the baseline target:

  • C/C++: -march=nehalem for x64 && baseline (scripts/build/flags.ts)
  • Rust: -Ctarget-cpu=nehalem for x64 baseline (scripts/build/rust.ts)

But WebKit is a prebuilt download, and oven-sh/WebKit publishes no baseline (Nehalem) macOS tarball. Only bun-webkit-macos-amd64.tar.gz (Haswell) exists for x64. A "baseline" darwin build therefore links that Haswell WebKit, whose bmalloc/WTF archives are full of BMI2 (llvm-objdump -d libbmalloc.a shows 313 shlx, 297 bzhi, etc.), and its startup constructors are the exact findAndRunAllInitializers frame in the crash.

Fix

resolveConfig() now refuses, at configure time, to produce a prebuilt baseline macOS build, with a message that points at the only correct alternative. This replaces the current failure modes (a cryptic 404 on bun-webkit-macos-amd64-baseline.tar.gz, or, if the -baseline suffix were dropped, silently re-linking the Haswell WebKit, which is how the broken binary shipped) with a clear, actionable error:

error: baseline builds are not supported for macOS: oven-sh/WebKit ships no
baseline (Nehalem) macOS WebKit, so the binary would link the Haswell build
and crash with SIGILL on pre-Haswell Intel Macs (oven-sh/bun#32511)
  hint: Omit --baseline for macOS x64, or pass --webkit=local to compile
        WebKit for Nehalem from source.

Exemptions: a local WebKit build (--webkit=local, compiled for Nehalem via computeCpuTargetFlags) and rust-only split builds (which produce libbun_rust.a and never link WebKit) are both allowed. The stale deps/webkit.ts comment that implied a macOS -baseline suffix is emitted is corrected to point at the guard.

This is the in-repo half of the fix: it guarantees Bun can never again silently ship a macOS binary that claims "baseline" but crashes on the CPUs baseline exists to support. It does not, by itself, give pre-Haswell Mac users a working binary.

What a complete fix still needs (cross-repo)

A true baseline macOS binary requires a Nehalem macos-amd64-baseline WebKit built and published in oven-sh/WebKit. Once that artifact exists, this guard can be relaxed and a darwin/x64/baseline lane added to .buildkite/ci.mjs (which today has no such lane, so the regular bun-darwin-x64 is the only macOS x64 artifact, and it is Haswell too). That WebKit build cannot be produced or verified in this environment.

Testing

test/internal/macos-cross-config.test.ts (extended) exercises resolveConfig directly with a mock toolchain, so it runs on every host with no build or SDK download:

  • prebuilt baseline macOS build is rejected
  • baseline macOS with --webkit=local is allowed
  • baseline macOS rust-only split build is allowed
  • non-baseline macOS still resolves to the plain Haswell WebKit tarball
  • linux x64 baseline still resolves to bun-webkit-linux-amd64-baseline (the suffix path is untouched)

This is a build-configuration fix under scripts/, so the standard git stash -- src/ packages/ fail-before cannot strip it. Verified manually instead: with the guard removed, the "rejects a prebuilt baseline macOS build" test fails (no throw); with it, all 24 tests pass. bunx tsc --noEmit -p scripts/build/tsconfig.json is clean.

oven-sh/WebKit publishes no baseline (Nehalem) macOS WebKit tarball, so a
"baseline" darwin x64 build links the Haswell macOS WebKit. Its bmalloc
startup constructors use BMI2/AVX2 and raise SIGILL on pre-Haswell Intel
Macs before main() runs, which is why the shipped bun-darwin-x64-baseline
crashed at launch on Ivy Bridge (#32511).

resolveConfig now fails at configure time with a clear message when a
prebuilt baseline macOS build is requested, pointing at the local-WebKit
alternative. Local WebKit builds (compiled for Nehalem) and rust-only
split builds are exempt. Also corrects the deps/webkit.ts comment that
claimed no macOS baseline suffix is emitted.
@robobun

robobun commented Jun 19, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 7:11 AM PT - Jun 19th, 2026

❌ @robobun, your commit c569640 has 1 failures in Build #63494 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 32512

That installs a local version of the PR into your bun-32512 executable, so you can run:

bun-32512 --bun

@github-actions

Copy link
Copy Markdown
Contributor

Found 1 issue this PR may fix:

  1. Illegal Instruction in macOS intel without AVX2 #26872 - Reports SIGILL crash on macOS Intel Xeon E5-2450 (no AVX2) when running bun-darwin-x64-baseline, same root cause as bun-darwin-x64-baseline crashes with SIGILL on Ivy Bridge CPUs due to BMI2 instructions #32511

If this is helpful, copy the block below into the PR description to auto-close this issue on merge.

Fixes #26872

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The head commit changed during the review from 59db942 to 2f95d0a.


Comment @coderabbitai help to get the list of available commands and usage tips.

@robobun

robobun commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator Author

Good catch, #26872 is the same root cause (SIGILL at launch on a no-AVX2 Intel Mac running bun-darwin-x64-baseline). I referenced both #32511 and #26872 in the description but deliberately did not use Fixes/Closes: this PR stops Bun from building and shipping a macOS binary mislabeled as "baseline", but it does not yet produce one that runs on pre-Haswell CPUs. That still needs a Nehalem (macos-amd64-baseline) WebKit built in oven-sh/WebKit, which is cross-repo. Keeping both issues open until a working baseline macOS artifact exists.

@robobun

robobun commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find any issues with the guard itself, but this is a release-engineering policy change (it blocks a previously-shipped artifact configuration pending cross-repo WebKit work) and CI is currently red on the musl lanes, so it's worth a human confirming both before merge.

Extended reasoning...

Overview

This PR adds a single configure-time assert() in scripts/build/config.ts:resolveConfig() that refuses to produce a baseline macOS build using prebuilt WebKit, since oven-sh/WebKit publishes no Nehalem macOS tarball and the resulting binary SIGILLs on pre-Haswell Intel Macs. It exempts --webkit=local and rust-only split builds, updates a stale comment in deps/webkit.ts, and adds five regression tests in test/internal/macos-cross-config.test.ts covering the rejection, both exemptions, and that non-baseline macOS / Linux baseline paths are unaffected.

Security risks

None. This is build-configuration logic only — no runtime code, no auth, no untrusted input. The assert reads only the already-resolved config booleans.

Level of scrutiny

Moderate. The code change is small, well-commented, and thoroughly tested, and the bug hunter found nothing. However, it is a release-engineering policy change: it intentionally blocks a build configuration that has previously shipped to users (bun-darwin-x64-baseline), and the PR is explicit that this is only the in-repo half of the fix — the user-facing issue stays open until a Nehalem macOS WebKit is built cross-repo. That trade-off (stop shipping a broken-labelled binary now vs. wait for the full fix) is a maintainer call, not something I should rubber-stamp.

Other factors

Buildkite is currently reporting failures on the x64-musl, x64-musl-baseline, and aarch64-musl build-bun lanes for the head commit. The new assert only fires for baseline && darwin, so it should not affect any musl lane (and two of the three failing lanes aren't baseline at all), which suggests the failures are unrelated infrastructure — but that should be confirmed before merge rather than assumed. The mockToolchain in the test file is missing hostCc/hostCxx keys relative to the Toolchain interface, but that's pre-existing in the file and the spread-with-undefined-fallback in resolveConfig handles it.

@robobun

robobun commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks. Confirmed the musl lanes are unrelated:

  • Structural: the new assert only fires for baseline && darwin && webkit==="prebuilt". No musl target (indeed no non-darwin target) can reach it, and two of the three lanes you saw aren't baseline at all.
  • What you saw: those red musl jobs were on build #63493, which got canceled when an autofix-ci formatting commit pushed over it. Its musl build-bun jobs are in state canceled, not failed (the aggregate check surfaces canceled as red). On the live build #63494 the x64-musl, x64-musl-baseline, and aarch64-musl lanes all pass build-cpp/build-rust and build-bun is running clean. The only genuine red on #63493 was one darwin test-bun flake in the test/bake SSG pages-router suite (dev-server timeouts/SIGKILL), also unrelated to this diff.

On the policy point: agreed, it's a maintainer call. This PR deliberately only stops Bun from building and shipping a macOS binary mislabeled as "baseline"; it does not restore a working one (that needs a Nehalem macOS WebKit in oven-sh/WebKit). #32511 and #26872 stay open until that lands.

The mockToolchain hostCc/hostCxx gap is pre-existing in that file and handled by resolveConfig's spread-with-undefined-fallback, so I left it alone to keep the diff scoped.

@robobun

robobun commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator Author

CI is red again, and on a different darwin lane than the previous run, which confirms darwin test-suite flakiness rather than anything in this diff:

  • build #63493: darwin x64 test-bun → test/bake SSG pages-router cases (dev-server timeouts / SIGKILL)
  • build #63494: darwin aarch64 test-bun → should link and unlink workspace package and should not leak using readable stream (leak-threshold / timing flakes, ~3s each)

Different lanes, different tests, none of them touching scripts/build/ or anything this PR changes. Every build-bun lane (x64/aarch64/musl/darwin/windows) passed, so the binary builds clean everywhere with the new guard; 285 of 286 real jobs are green and the one red is a flake that moves around between runs.

I've used my one retrigger (build #63494) and won't push another to avoid noise. The diff stands on its own for review. As noted in the description, merging is a maintainer call: it's a deliberate release-engineering change (stops building/shipping a macOS binary mislabeled "baseline"), and a binary that actually runs on pre-Haswell Macs additionally needs a Nehalem macos-amd64 WebKit in oven-sh/WebKit.

@robobun

robobun commented Sep 12, 2026

Copy link
Copy Markdown
Collaborator Author

Stale PR review: closing.

This PR has had no human activity since it was opened on 2026-06-19 and it conflicts with main. The mislabeled build it guards against can no longer exist: #34782 (e550f2c) and oven-sh/WebKit@541f498e4d made every x64 build a single Nehalem build with one WebKit tarball per platform, and #32511 was closed as completed on that basis. On main baseline defaults to true for every x64 target (scripts/build/config.ts:875), -march=nehalem is the only x64 entry (scripts/build/flags.ts:71), and prebuiltSuffix() has no -baseline branch (scripts/build/deps/webkit.ts:58). The assert in this PR would now reject the default darwin-x64 release build (.buildkite/ci.mjs:148). The remaining crash on Macs without AVX comes from the JIT and stays tracked in #26872 and #34215.

Reopen if this evidence is wrong.

@robobun robobun closed this Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant