From 8a68dc7bdd3d1c97677a6633a4f2b5e524c492ae Mon Sep 17 00:00:00 2001 From: Max Bernstein Date: Mon, 24 Nov 2025 12:28:30 -0800 Subject: [PATCH 1/3] Revert "Fix stdatomic case in `rbimpl_atomic_u64_fetch_add`" (#15311) This reverts commit d3b6f835d565ec1590059773fc87589ddf8adc37. This broke the Docker builds and presumably also 32-bit machines that don't already have libatomic installed. --- configure.ac | 1 - ruby_atomic.h | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 1e406ec56cff8a..339ee3b2f2e66e 100644 --- a/configure.ac +++ b/configure.ac @@ -1746,7 +1746,6 @@ AS_IF([test "$GCC" = yes], [ [rb_cv_gcc_atomic_builtins=no])]) AS_IF([test "$rb_cv_gcc_atomic_builtins" = yes], [ AC_DEFINE(HAVE_GCC_ATOMIC_BUILTINS) - AC_CHECK_LIB([atomic], [__atomic_fetch_add_8]) AC_CACHE_CHECK([for 64bit __atomic builtins], [rb_cv_gcc_atomic_builtins_64], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include uint64_t atomic_var;]], diff --git a/ruby_atomic.h b/ruby_atomic.h index 3a541d92082824..c194f7ec3b82fc 100644 --- a/ruby_atomic.h +++ b/ruby_atomic.h @@ -2,9 +2,6 @@ #define INTERNAL_ATOMIC_H #include "ruby/atomic.h" -#ifdef HAVE_STDATOMIC_H -# include -#endif #define RUBY_ATOMIC_VALUE_LOAD(x) rbimpl_atomic_value_load(&(x), RBIMPL_ATOMIC_SEQ_CST) @@ -79,9 +76,9 @@ rbimpl_atomic_u64_fetch_add(volatile rbimpl_atomic_uint64_t *ptr, uint64_t val) return InterlockedExchangeAdd64((volatile LONG64 *)ptr, val); #elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) return atomic_add_64_nv(ptr, val) - val; -#elif defined(HAVE_STDATOMIC_H) - return atomic_fetch_add_explicit((_Atomic uint64_t *)ptr, val, memory_order_seq_cst); #else + // TODO: stdatomic + // Fallback using mutex for platforms without 64-bit atomics static rb_native_mutex_t lock = RB_NATIVE_MUTEX_INITIALIZER; rb_native_mutex_lock(&lock); From 2315349b8ac10b1b4468ed10dabcb348a10bca0a Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Sun, 23 Nov 2025 17:34:44 -0500 Subject: [PATCH 2/3] Handle SIGABRT and output bug report SIGABRT is for abnormal termination so we should handle it to output a bug report. Specifically, glibc malloc uses it to exit when there is corruption. For example, the following script produces a double free: mem = Fiddle.malloc(10) Fiddle.free(mem) Fiddle.free(mem) Before this patch, it just outputs the following and exits: free(): double free detected in tcache 2 After this patch, it also outputs a bug report: free(): double free detected in tcache 2 test.rb:11: [BUG] Aborted at 0x000003e8000ab65c --- signal.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/signal.c b/signal.c index f6b62b30147d87..1e2b0f613248c2 100644 --- a/signal.c +++ b/signal.c @@ -949,6 +949,20 @@ sigsegv(int sig SIGINFO_ARG) } #endif +#ifdef SIGABRT + +static sighandler_t default_sigabrt_handler; +NORETURN(static ruby_sigaction_t sigabrt); + +static void +sigabrt(int sig SIGINFO_ARG) +{ + check_reserved_signal("ABRT"); + CHECK_STACK_OVERFLOW(); + rb_bug_for_fatal_signal(default_sigabrt_handler, sig, SIGINFO_CTX, "Aborted" MESSAGE_FAULT_ADDRESS); +} +#endif + #ifdef SIGILL static sighandler_t default_sigill_handler; @@ -1558,6 +1572,10 @@ Init_signal(void) RB_ALTSTACK_INIT(GET_VM()->main_altstack, rb_allocate_sigaltstack()); force_install_sighandler(SIGSEGV, (sighandler_t)sigsegv, &default_sigsegv_handler); #endif + +#ifdef SIGABRT + force_install_sighandler(SIGABRT, (sighandler_t)sigabrt, &default_sigabrt_handler); +#endif } #ifdef SIGPIPE install_sighandler(SIGPIPE, sig_do_nothing); From 35445a736f509e6edbba8a08d8e4af69c206368a Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Sun, 23 Nov 2025 20:36:52 -0500 Subject: [PATCH 3/3] Add SIGABRT to reserved signals in bundler spec --- spec/bundler/commands/exec_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb index 1ac308bdda4bfc..19e836053fa141 100644 --- a/spec/bundler/commands/exec_spec.rb +++ b/spec/bundler/commands/exec_spec.rb @@ -1020,7 +1020,7 @@ def bin_path(a,b,c) context "signal handling" do let(:test_signals) do open3_reserved_signals = %w[CHLD CLD PIPE] - reserved_signals = %w[SEGV BUS ILL FPE VTALRM KILL STOP EXIT] + reserved_signals = %w[SEGV BUS ILL FPE ABRT IOT VTALRM KILL STOP EXIT] bundler_signals = %w[INT] Signal.list.keys - (bundler_signals + reserved_signals + open3_reserved_signals)