From 7fb78a081b8272034515dcb74e18034f5f71363d Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 27 Aug 2014 08:15:20 +0400 Subject: [PATCH] Fix some glitches in previous change. * sysdep.c (stack_direction): Replace stack_grows_down to simplify calculation of stack boundaries. (handle_sigsegv): Check whether we really crash somewhere near to stack boundary, and handle fatal signal as usual if not. (init_sigsegv): Adjust accordingly. --- src/ChangeLog | 9 +++++++++ src/keyboard.c | 2 +- src/sysdep.c | 30 +++++++++++++++++++----------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 44b0bcf0b78..8bc6c1069ad 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2014-08-27 Dmitry Antipov + + Fix some glitches in previous change. + * sysdep.c (stack_direction): Replace stack_grows_down + to simplify calculation of stack boundaries. + (handle_sigsegv): Check whether we really crash somewhere near + to stack boundary, and handle fatal signal as usual if not. + (init_sigsegv): Adjust accordingly. + 2014-08-26 Dmitry Antipov Handle C stack overflow caused by too nested Lisp evaluation. diff --git a/src/keyboard.c b/src/keyboard.c index ed00b38a7db..79b3aec3304 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -11028,7 +11028,7 @@ syms_of_keyboard (void) #ifdef HAVE_STACK_OVERFLOW_HANDLING recover_top_level_message = build_pure_c_string ("Re-entering top level after C stack overflow"); -#endif +#endif DEFVAR_LISP ("top-level-message", Vtop_level_message, doc: /* Message displayed by `normal-top-level'. */); Vtop_level_message = regular_top_level_message; diff --git a/src/sysdep.c b/src/sysdep.c index c0d651b296a..7b93cb93b85 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1720,9 +1720,9 @@ handle_arith_signal (int sig) #ifdef HAVE_STACK_OVERFLOW_HANDLING -/* True if stack grows down as expected on most OS/ABI variants. */ +/* -1 if stack grows down as expected on most OS/ABI variants, 1 otherwise. */ -static bool stack_grows_down; +static int stack_direction; /* Alternate stack used by SIGSEGV handler below. */ @@ -1741,17 +1741,25 @@ handle_sigsegv (int sig, siginfo_t *siginfo, void *arg) if (!getrlimit (RLIMIT_STACK, &rlim)) { - enum { STACK_EXTRA = 16 * 1024 }; - char *fault_addr = (char *) siginfo->si_addr; - unsigned long used = (stack_grows_down - ? stack_bottom - fault_addr - : fault_addr - stack_bottom); - - if (used + STACK_EXTRA > rlim.rlim_cur) - /* Most likely this is it. */ + enum { STACK_DANGER_ZONE = 16 * 1024 }; + char *beg, *end, *addr; + + beg = stack_bottom; + end = stack_bottom + stack_direction * rlim.rlim_cur; + if (beg > end) + addr = beg, beg = end, end = addr; + addr = (char *) siginfo->si_addr; + /* If we're somewhere on stack and too close to + one of its boundaries, most likely this is it. */ + if (beg < addr && addr < end + && (addr - beg < STACK_DANGER_ZONE + || end - addr < STACK_DANGER_ZONE)) siglongjmp (return_to_command_loop, 1); } } + + /* Otherwise we can't do anything with this. */ + deliver_fatal_thread_signal (sig); } /* Return true if we have successfully set up SIGSEGV handler on alternate @@ -1763,7 +1771,7 @@ init_sigsegv (void) struct sigaction sa; stack_t ss; - stack_grows_down = ((char *) &ss < stack_bottom); + stack_direction = ((char *) &ss < stack_bottom) ? -1 : 1; ss.ss_sp = sigsegv_stack; ss.ss_size = sizeof (sigsegv_stack); -- 2.39.5