Skip to content

Commit 09c7ee5

Browse files
committed
Avoid infinite recursion when raising SIGABRT in SIGABRT handler
When VM state is corrupted enough, we can call abort() from the SIGABRT handler. Previously, we would spam until the stack is full: ABRT received in SEGV handler SEGV received in ABRT handler ABRT received in SEGV handler ABRT received in ABRT handler ABRT received in ABRT handler ABRT received in ABRT handler [...] We've since this on CI on for example: https://github.com/ruby/ruby/actions/runs/26591192708/job/78350130653 To test this situation locally, temporarily patch in a call to abort() in rb_bug_for_fatal_signal() then use `Process.kill(:ABRT, Process.pid)`. Fix by restoring the default signal handler before aborting.
1 parent 63d9f09 commit 09c7ee5

1 file changed

Lines changed: 13 additions & 1 deletion

File tree

signal.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1020,8 +1020,20 @@ check_reserved_signal_(const char *name, size_t name_len, int signo)
10201020
#if __has_feature(address_sanitizer) || \
10211021
__has_feature(memory_sanitizer) || \
10221022
defined(HAVE_VALGRIND_MEMCHECK_H)
1023-
ruby_posix_signal(signo, SIG_DFL);
1023+
# define FIRST_COND true
1024+
#else
1025+
# define FIRST_COND false
1026+
#endif
1027+
1028+
#ifdef SIGABRT
1029+
// Avoid infinite loop when already aborting
1030+
# define SECOND_COND (signo == SIGABRT)
1031+
#else
1032+
# define SECOND_COND false
10241033
#endif
1034+
if (FIRST_COND || SECOND_COND) ruby_signal(signo, SIG_DFL);
1035+
# undef FIRST_COND
1036+
# undef SECOND_COND
10251037
W(name, name_len);
10261038
W(msg1, sizeof(msg1));
10271039
W(prev, strlen(prev));

0 commit comments

Comments
 (0)