=== modified file 'lisp/startup.el' --- lisp/startup.el 2014-07-27 13:21:30 +0000 +++ lisp/startup.el 2014-08-25 13:33:17 +0000 @@ -497,7 +497,7 @@ reads the initialization files, etc. It is the default value of the variable `top-level'." (if command-line-processed - (message "Back to top level.") + (message top-level-message) (setq command-line-processed t) ;; Look in each dir in load-path for a subdirs.el file. If we === modified file 'src/keyboard.c' --- src/keyboard.c 2014-08-10 08:26:28 +0000 +++ src/keyboard.c 2014-08-25 14:11:14 +0000 @@ -133,6 +133,15 @@ static ptrdiff_t before_command_key_count; static ptrdiff_t before_command_echo_length; +/* For longjmp to recover from C stack overflow. */ +sys_jmp_buf return_to_command_loop; + +/* Message displayed by Vtop_level when we recover from C stack overflow. */ +static Lisp_Object recover_top_level_message; + +/* Message normally displayed by Vtop_level. */ +static Lisp_Object regular_top_level_message; + /* For longjmp to where kbd input is being done. */ static sys_jmp_buf getcjmp; @@ -1134,6 +1143,16 @@ Lisp_Object command_loop (void) { + /* Saving signal mask looks important here. */ + if (sigsetjmp (return_to_command_loop, 1) != 0) + { + /* Comes here after recovering from C stack overflow. */ + init_eval (); + Vtop_level_message = recover_top_level_message; + } + else + Vtop_level_message = regular_top_level_message; + if (command_loop_level > 0 || minibuf_level > 0) { Lisp_Object val; @@ -11000,6 +11019,13 @@ Vlispy_mouse_stem = build_pure_c_string ("mouse"); staticpro (&Vlispy_mouse_stem); + regular_top_level_message = build_pure_c_string ("Back to top level"); + recover_top_level_message + = build_pure_c_string ("Re-entering top level after C stack overflow"); + DEFVAR_LISP ("top-level-message", Vtop_level_message, + doc: /* Message displayed by `normal-top-level'. */); + Vtop_level_message = regular_top_level_message; + /* Tool-bars. */ DEFSYM (QCimage, ":image"); DEFSYM (Qhelp_echo, "help-echo"); === modified file 'src/lisp.h' --- src/lisp.h 2014-08-25 05:44:57 +0000 +++ src/lisp.h 2014-08-25 14:11:23 +0000 @@ -4093,6 +4093,7 @@ extern Lisp_Object Qup, Qdown; extern Lisp_Object last_undo_boundary; extern bool input_pending; +extern sys_jmp_buf return_to_command_loop; extern Lisp_Object menu_bar_items (Lisp_Object); extern Lisp_Object tool_bar_items (Lisp_Object, int *); extern void discard_mouse_events (void); === modified file 'src/sysdep.c' --- src/sysdep.c 2014-08-25 05:44:57 +0000 +++ src/sysdep.c 2014-08-25 14:43:34 +0000 @@ -46,7 +46,6 @@ # include # undef frame -# include # include #endif @@ -72,6 +71,7 @@ #include "msdos.h" #endif +#include #include #include #include @@ -1716,6 +1716,31 @@ xsignal0 (Qarith_error); } +/* Attempt to recover from SIGSEGV caused by C stack overflow. */ + +static void +handle_sigsegv (int sig, siginfo_t *siginfo, void *arg) +{ + /* Hard GC error may lead to C stack overflow caused by + too nested calls to mark_object. No way to survive. */ + if (!gc_in_progress) + { + struct rlimit rlim; + unsigned long used; + enum { STACK_EXTRA = 16 * 1024 }; + char *fault_addr = (char *) siginfo->si_addr; + + getrlimit (RLIMIT_STACK, &rlim); + if (fault_addr > stack_bottom) + used = fault_addr - stack_bottom; + else + used = stack_bottom - fault_addr; + if (used + STACK_EXTRA > rlim.rlim_cur) + /* Most likely this is it. */ + sys_longjmp (return_to_command_loop, 1); + } +} + static void deliver_arith_signal (int sig) { @@ -1761,7 +1786,9 @@ init_signals (bool dumping) { struct sigaction thread_fatal_action; + struct sigaction sigsegv_action; struct sigaction action; + stack_t altstack; sigemptyset (&empty_mask); @@ -1912,6 +1939,18 @@ if (dumping) return; + /* Alternate stack used to handle SIGSEGV. */ + altstack.ss_sp = xmalloc (SIGSTKSZ); + altstack.ss_size = SIGSTKSZ; + altstack.ss_flags = 0; + if (sigaltstack (&altstack, NULL) < 0) + emacs_abort (); + + /* This is special because we need fault address. */ + sigfillset (&sigsegv_action.sa_mask); + sigsegv_action.sa_sigaction = handle_sigsegv; + sigsegv_action.sa_flags = emacs_sigaction_flags () | SA_SIGINFO | SA_ONSTACK; + sigfillset (&process_fatal_action.sa_mask); process_fatal_action.sa_handler = deliver_fatal_signal; process_fatal_action.sa_flags = emacs_sigaction_flags (); @@ -1982,7 +2021,7 @@ #ifdef SIGBUS sigaction (SIGBUS, &thread_fatal_action, 0); #endif - sigaction (SIGSEGV, &thread_fatal_action, 0); + sigaction (SIGSEGV, &sigsegv_action, 0); #ifdef SIGSYS sigaction (SIGSYS, &thread_fatal_action, 0); #endif