Misc #22320
openBuild fails with SIGSEGV in `miniruby` during `builtin_binary` on macOS 26 (Tahoe): `pipe2` declared by SDK but absent from libSystem at runtime
Description
Environment
- macOS 26.6.2 (Tahoe), Apple Silicon (arm64)
- Apple clang 21.0.0 (clang-2100.3.34.2), target
arm64-apple-darwin25.6.0 - Ruby 3.4.10 (also reproduced on 4.0.7), built via ruby-build 20260915 / rbenv
- Also reproduces with a plain
./configure && makefrom the release tarball
Summary
On macOS 26, make dies with Segmentation fault: 11 at the step that runs the freshly-linked miniruby to generate builtin_binary.inc (builtin_binary.rbbin). Every Ruby version fails identically, because miniruby segfaults on launch during interpreter init.
compiling enc/trans/newline.c
linking miniruby
make: *** [builtin_binary.inc] Segmentation fault: 11
Root cause
macOS 26's SDK now declares pipe2() in its headers, so Ruby's configure sets HAVE_PIPE2 and rb_cloexec_pipe() compiles a call to pipe2. However, libSystem does not actually provide the symbol at runtime. The weak-imported _pipe2 binds to NULL, and the call during timer-thread setup jumps to address 0.
Crash report (~/Library/Logs/DiagnosticReports/miniruby-*.ips):
Exception: EXC_BAD_ACCESS (SIGSEGV), KERN_INVALID_ADDRESS at 0x0000000000000000
Faulting thread frames:
0x0 ← call through NULL function pointer
miniruby rb_cloexec_pipe
miniruby setup_communication_pipe_internal
miniruby rb_thread_create_timer_thread
miniruby Init_Thread
miniruby rb_call_inits
miniruby ruby_setup / ruby_init
miniruby main
dyld start
Confirmation that pipe2 is declared but not present at runtime:
$ cat > /tmp/pipe2test.c <<'EOF'
#include <stdio.h>
extern int pipe2(int[2], int);
int main(void){ printf("%p\n", (void*)pipe2); return 0; }
EOF
$ clang -o /tmp/pipe2test /tmp/pipe2test.c && /tmp/pipe2test
dyld[]: Symbol not found: _pipe2
Expected in: /usr/lib/libSystem.B.dylib
Steps to reproduce
- On macOS 26 (Apple Silicon), build Ruby 3.4.x from source (
./configure && make). makesegfaults atbuiltin_binary.incwhile executingminiruby.
Expected
configure should not enable HAVE_PIPE2 when the symbol is declared but unavailable at runtime, or rb_cloexec_pipe should guard the call (e.g. __builtin_available / weak-symbol NULL check) and fall back to pipe() + FD_CLOEXEC.
Actual
HAVE_PIPE2 is enabled based solely on the declaration; the resulting binary calls a NULL symbol and crashes.
Workaround
ac_cv_func_pipe2=no ./configure ...
# or, with rbenv:
RUBY_CONFIGURE_OPTS="ac_cv_func_pipe2=no" rbenv install 3.4.10
Suggested fix
Make the pipe2 detection on Darwin a link-and-availability test rather than a declaration check, or wrap the call site with an availability guard so it degrades to the pipe() fallback when &pipe2 == NULL. (macOS historically lacked pipe2; the macOS 26 SDK appears to declare it ahead of libSystem actually providing it.)
No data to display