diff options
author | Koichi Sasada <ko1@atdot.net> | 2020-11-30 05:07:28 +0900 |
---|---|---|
committer | Koichi Sasada <ko1@atdot.net> | 2020-11-30 05:10:48 +0900 |
commit | 77936ad679d63a6d0e7b585db4c31db5507f5586 (patch) | |
tree | 69b378c6155c066175d88bebdd1f2f132b130de2 /gc.c | |
parent | 02c32b2e9299726e20bb4499fa7c1f5430ce0b6d (diff) |
support SIGSEGV/BUS while read_barrier_handler()
read_barrier_handler() can cause SIGSEGV/BUS so it should show
the errors.
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 29 |
1 files changed, 18 insertions, 11 deletions
@@ -4597,18 +4597,25 @@ static struct sigaction old_sigsegv_handler; static void read_barrier_signal(int sig, siginfo_t * info, void * data) { - extern int ruby_on_ci; - if (ruby_on_ci) { // `read_barrier_handler` may crash. Report backtraces first on CI. -# if HAVE_BACKTRACE // `rb_bug_without_die` may crash on `control_frame_dump`. Report a C backtrace first. - fprintf(stderr, "-- C level backtrace (read_barrier_signal) " - "-------------------------------------------\n"); - rb_print_backtrace(); - fprintf(stderr, "\n"); -# endif - extern void rb_bug_without_die(const char *fmt, ...); - rb_bug_without_die("died with read_barrier_signal installed"); - } + // setup SEGV/BUS handlers for errors + struct sigaction prev_sigbus, prev_sigsegv; + sigaction(SIGBUS, &old_sigbus_handler, &prev_sigbus); + sigaction(SIGSEGV, &old_sigsegv_handler, &prev_sigsegv); + + // enable SIGBUS/SEGV + sigset_t set, prev_set; + sigemptyset(&set); + sigaddset(&set, SIGBUS); + sigaddset(&set, SIGSEGV); + sigprocmask(SIG_UNBLOCK, &set, &prev_set); + + // run handler read_barrier_handler((intptr_t)info->si_addr); + + // reset SEGV/BUS handlers + sigaction(SIGBUS, &prev_sigbus, NULL); + sigaction(SIGSEGV, &prev_sigsegv, NULL); + sigprocmask(SIG_SETMASK, &prev_set, NULL); } static void uninstall_handlers(void) |