Skip to content

Fix Android/FreeBSD runtime issues found by running the test suite - #38237

Closed
dylan-conway wants to merge 2 commits into
mainfrom
claude/bun-android-freebsd-testing-488481
Closed

Fix Android/FreeBSD runtime issues found by running the test suite#38237
dylan-conway wants to merge 2 commits into
mainfrom
claude/bun-android-freebsd-testing-488481

Conversation

@dylan-conway

Copy link
Copy Markdown
Member

What does this PR do?

Running the full test suite (via scripts/runner.node.mjs, as CI does) on the FreeBSD x64 and Android x64 artifacts turned up several platform-specific runtime bugs; this fixes the ones with clear root causes and teaches the runner/harness about both hosts.

  • Android bun build --compile: every compiled executable segfaulted at startup. Standalone binaries are PIE on Android, so the embedded module graph's link-time vaddr now gets the load bias (found via dl_iterate_phdr) added before it is dereferenced.
  • FreeBSD --compile on UFS: inject() now returns the temp path it created instead of the caller reverse-mapping fd→path (F_KINFO returned an empty path there, so the final rename failed with ENOENT).
  • FreeBSD stack overflow → SIGILL: dropped -z stack-size from the FreeBSD link. FreeBSD's exec uses PT_GNU_STACK as the main-thread stack reservation while libthr reports RLIMIT_STACK, so overflow guards never fired and deep recursion (TOML/YAML/JSONC/transpiler tests) killed the process instead of throwing RangeError.
  • FreeBSD uname: the exported uname symbol fills 32-byte fields; call __xuname(256, …) so utsname.release isn't empty (crash reports printed FreeBSD Kernel v).
  • FreeBSD kqueue: ignore EV_ERROR/ENOENT|EBADF receipts from cancelling an already-fired oneshot knote; they were surfacing as read errors for FIFOs/pipes via Bun.file().
  • FreeBSD PTY: load openpty from libutil so Bun.Terminal works.
  • scripts/utils.mjs / test/harness.ts: recognize freebsd and android.

How did you verify your code works?

Linux: bun bd build --compile (plain, --bytecode, nested --outfile) produces working binaries; test/bundler/bun-build-compile.test.ts unchanged vs main. cargo check passes for x86_64-unknown-freebsd and x86_64-linux-android. The FreeBSD/Android behavior changes were diagnosed on a FreeBSD 14.3 VM and an API 35 x86_64 emulator against the current artifacts; re-verification on-target is pending this PR's CI artifacts.

…suite

- --compile on Android: standalone executables are PIE there, so the
  embedded module graph's link-time vaddr must be adjusted by the load
  bias before dereferencing (every compiled binary segfaulted at startup).
- --compile on FreeBSD/UFS: carry the temp path out of inject() instead
  of reverse-mapping fd -> path, which came back empty via F_KINFO and
  made the final rename fail with ENOENT.
- FreeBSD: drop -z stack-size from the link. FreeBSD's exec uses
  PT_GNU_STACK's size as the main-thread stack reservation while libthr
  reports RLIMIT_STACK, so stack-overflow guards never fired and deep
  recursion died with SIGILL instead of throwing RangeError.
- FreeBSD: call __xuname(256, ...) for uname; the exported `uname`
  symbol fills 32-byte fields, leaving utsname.release empty.
- FreeBSD kqueue: ignore EV_ERROR/ENOENT|EBADF receipts for a Cancel of
  an already-fired oneshot knote instead of surfacing them as read errors
  (broke reading FIFOs/pipes via Bun.file()).
- FreeBSD: enable Bun.Terminal / PTY by dlopen'ing openpty from libutil.
- Test runner + harness: recognize freebsd and android hosts.
@robobun

robobun commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator
Updated 1:55 PM PT - Aug 13th, 2026

@dylan-conway, your commit d5249e9 is building: #94954

The receive side passed msg_controllen = CMSG_LEN(sizeof(int)), which is
4 bytes short of the aligned size on FreeBSD (12-byte cmsghdr, 8-byte
alignment: 20 vs 24). FreeBSD then sets MSG_CTRUNC and discards the
descriptor, so every handle sent over IPC (cluster, child_process.fork
with a server/socket) was lost and the receiver hung. Linux tolerates the
short buffer and on macOS the two sizes are equal, which is why this
never showed up before.

Also gate the FORCE_WAITER_THREAD self-test in spawn.test.ts on Linux:
the waiter thread is the pidfd-less Linux fallback and its non-Linux loop
has no wakeup, so running it on FreeBSD hangs.
@github-actions

Copy link
Copy Markdown
Contributor

Found 2 issues this PR may fix:

  1. bun build --compile doesn't work correctly in a dev container #12318 - Reports the exact failed to rename ....bun-build to mycli: ENOENT message from to_executable, caused by recovering the temp path via get_fd_path(fd) (readlink /proc/self/fd/N), which returns a host-namespace path under a dev container virtiofs mount — this PR drops that reverse-mapping in favor of injected.temp_path.
  2. Bun failes to rename compiled executable when in a folder mounted from Docker #10046 - Same failure on a Docker bind-mounted folder (.bun-build temp file left behind, manual rename produces a working binary, works fine when not mounted), fixed by the same Injected { fd, temp_path } change.

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

Fixes #12318
Fixes #10046

🤖 Generated with Claude Code

@dylan-conway

Copy link
Copy Markdown
Member Author

Split into #38242 (FreeBSD) and the Android PR; closing this combined draft.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants