mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
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 seen this on CI:
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.
This commit is contained in:
1 parent
9c62016982
commit
3a5a46f8ad
1 file changed
+13
-1
Notes:
git
2026-07-07 18:14:04 +00:00
@@ -1020,8 +1020,20 @@ check_reserved_signal_(const char *name, size_t name_len, int signo)
|
||||
#if __has_feature(address_sanitizer) || \
|
||||
__has_feature(memory_sanitizer) || \
|
||||
defined(HAVE_VALGRIND_MEMCHECK_H)
|
||||
ruby_posix_signal(signo, SIG_DFL);
|
||||
# define SANITIZING true
|
||||
#else
|
||||
# define SANITIZING false
|
||||
#endif
|
||||
|
||||
#ifdef SIGABRT
|
||||
// Avoid infinite loop when already aborting
|
||||
# define RECURSIVE (signo == SIGABRT)
|
||||
#else
|
||||
# define RECURSIVE false
|
||||
#endif
|
||||
if (SANITIZING || RECURSIVE) ruby_signal(signo, SIG_DFL);
|
||||
# undef SANITIZING
|
||||
# undef RECURSIVE
|
||||
W(name, name_len);
|
||||
W(msg1, sizeof(msg1));
|
||||
W(prev, strlen(prev));
|
||||
|
||||
Reference in new issue
Block a user