+2014-08-27 Dmitry Antipov <dmantipov@yandex.ru>
+
+ 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 <dmantipov@yandex.ru>
Handle C stack overflow caused by too nested Lisp evaluation.
#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;
#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. */
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
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);