aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-07-14 04:54:05 -0700
committerPaul Eggert2017-07-14 04:57:18 -0700
commit9dee1c884eb50ba282eb9dd2495c5269add25963 (patch)
tree947b4c3c21e4bef82795cfbd60f29e371b0e2cc3 /src
parent6443a95ad74d54b8be5ba85af9b893f3f1d5fa02 (diff)
downloademacs-9dee1c884eb50ba282eb9dd2495c5269add25963.tar.gz
emacs-9dee1c884eb50ba282eb9dd2495c5269add25963.zip
Improve stack-overflow heuristic on GNU/Linux
Problem reported by Steve Kemp (Bug#27585). * src/eval.c (near_C_stack_top): Remove. All uses replaced by current_thread->stack_top. (record_in_backtrace): Set current_thread->stack_top. This is for when the Lisp interpreter calls itself. * src/lread.c (read1): Set current_thread->stack_top. This is for recursive s-expression reads. * src/print.c (print_object): Set current_thread->stack_top. This is for recursive s-expression printing. * src/thread.c (mark_one_thread): Get stack top first. * src/thread.h (struct thread_state.stack_top): Now void *, not char *.
Diffstat (limited to 'src')
-rw-r--r--src/eval.c9
-rw-r--r--src/lisp.h1
-rw-r--r--src/lread.c1
-rw-r--r--src/print.c2
-rw-r--r--src/sysdep.c2
-rw-r--r--src/thread.c10
-rw-r--r--src/thread.h10
7 files changed, 18 insertions, 17 deletions
diff --git a/src/eval.c b/src/eval.c
index 8f293c9d300..e5900382dee 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -213,13 +213,6 @@ backtrace_next (union specbinding *pdl)
213 return pdl; 213 return pdl;
214} 214}
215 215
216/* Return a pointer to somewhere near the top of the C stack. */
217void *
218near_C_stack_top (void)
219{
220 return backtrace_args (backtrace_top ());
221}
222
223void 216void
224init_eval_once (void) 217init_eval_once (void)
225{ 218{
@@ -2090,7 +2083,7 @@ record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs)
2090 specpdl_ptr->bt.kind = SPECPDL_BACKTRACE; 2083 specpdl_ptr->bt.kind = SPECPDL_BACKTRACE;
2091 specpdl_ptr->bt.debug_on_exit = false; 2084 specpdl_ptr->bt.debug_on_exit = false;
2092 specpdl_ptr->bt.function = function; 2085 specpdl_ptr->bt.function = function;
2093 specpdl_ptr->bt.args = args; 2086 current_thread->stack_top = specpdl_ptr->bt.args = args;
2094 specpdl_ptr->bt.nargs = nargs; 2087 specpdl_ptr->bt.nargs = nargs;
2095 grow_specpdl (); 2088 grow_specpdl ();
2096 2089
diff --git a/src/lisp.h b/src/lisp.h
index f5cb6c75706..1e8ef7a449a 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3874,7 +3874,6 @@ extern Lisp_Object vformat_string (const char *, va_list)
3874 ATTRIBUTE_FORMAT_PRINTF (1, 0); 3874 ATTRIBUTE_FORMAT_PRINTF (1, 0);
3875extern void un_autoload (Lisp_Object); 3875extern void un_autoload (Lisp_Object);
3876extern Lisp_Object call_debugger (Lisp_Object arg); 3876extern Lisp_Object call_debugger (Lisp_Object arg);
3877extern void *near_C_stack_top (void);
3878extern void init_eval_once (void); 3877extern void init_eval_once (void);
3879extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...); 3878extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...);
3880extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object); 3879extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object);
diff --git a/src/lread.c b/src/lread.c
index fe5de382677..901e40b3489 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -2676,6 +2676,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2676 bool uninterned_symbol = false; 2676 bool uninterned_symbol = false;
2677 bool multibyte; 2677 bool multibyte;
2678 char stackbuf[MAX_ALLOCA]; 2678 char stackbuf[MAX_ALLOCA];
2679 current_thread->stack_top = stackbuf;
2679 2680
2680 *pch = 0; 2681 *pch = 0;
2681 2682
diff --git a/src/print.c b/src/print.c
index b6ea3ff62a5..12edf015892 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1748,7 +1748,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1748 char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT), 1748 char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT),
1749 max (sizeof " . #" + INT_STRLEN_BOUND (printmax_t), 1749 max (sizeof " . #" + INT_STRLEN_BOUND (printmax_t),
1750 40))]; 1750 40))];
1751 1751 current_thread->stack_top = buf;
1752 maybe_quit (); 1752 maybe_quit ();
1753 1753
1754 /* Detect circularities and truncate them. */ 1754 /* Detect circularities and truncate them. */
diff --git a/src/sysdep.c b/src/sysdep.c
index b52236769e0..db99f53299c 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -1772,7 +1772,7 @@ stack_overflow (siginfo_t *siginfo)
1772 /* The known top and bottom of the stack. The actual stack may 1772 /* The known top and bottom of the stack. The actual stack may
1773 extend a bit beyond these boundaries. */ 1773 extend a bit beyond these boundaries. */
1774 char *bot = stack_bottom; 1774 char *bot = stack_bottom;
1775 char *top = near_C_stack_top (); 1775 char *top = current_thread->stack_top;
1776 1776
1777 /* Log base 2 of the stack heuristic ratio. This ratio is the size 1777 /* Log base 2 of the stack heuristic ratio. This ratio is the size
1778 of the known stack divided by the size of the guard area past the 1778 of the known stack divided by the size of the guard area past the
diff --git a/src/thread.c b/src/thread.c
index e3787971a53..1f7ced386d3 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -595,14 +595,15 @@ thread_select (select_func *func, int max_fds, fd_set *rfds,
595static void 595static void
596mark_one_thread (struct thread_state *thread) 596mark_one_thread (struct thread_state *thread)
597{ 597{
598 struct handler *handler; 598 /* Get the stack top now, in case mark_specpdl changes it. */
599 Lisp_Object tem; 599 void *stack_top = thread->stack_top;
600 600
601 mark_specpdl (thread->m_specpdl, thread->m_specpdl_ptr); 601 mark_specpdl (thread->m_specpdl, thread->m_specpdl_ptr);
602 602
603 mark_stack (thread->m_stack_bottom, thread->stack_top); 603 mark_stack (thread->m_stack_bottom, stack_top);
604 604
605 for (handler = thread->m_handlerlist; handler; handler = handler->next) 605 for (struct handler *handler = thread->m_handlerlist;
606 handler; handler = handler->next)
606 { 607 {
607 mark_object (handler->tag_or_ch); 608 mark_object (handler->tag_or_ch);
608 mark_object (handler->val); 609 mark_object (handler->val);
@@ -610,6 +611,7 @@ mark_one_thread (struct thread_state *thread)
610 611
611 if (thread->m_current_buffer) 612 if (thread->m_current_buffer)
612 { 613 {
614 Lisp_Object tem;
613 XSETBUFFER (tem, thread->m_current_buffer); 615 XSETBUFFER (tem, thread->m_current_buffer);
614 mark_object (tem); 616 mark_object (tem);
615 } 617 }
diff --git a/src/thread.h b/src/thread.h
index 9e94de5c175..52b16f1ba83 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -62,8 +62,14 @@ struct thread_state
62 char *m_stack_bottom; 62 char *m_stack_bottom;
63#define stack_bottom (current_thread->m_stack_bottom) 63#define stack_bottom (current_thread->m_stack_bottom)
64 64
65 /* An address near the top of the stack. */ 65 /* The address of an object near the C stack top, used to determine
66 char *stack_top; 66 which words need to be scanned by the garbage collector. This is
67 also used to detect heuristically whether segmentation violation
68 address indicates stack overflow, as opposed to some internal
69 error in Emacs. If the C function F calls G which calls H which
70 calls ... F, then at least one of the functions in the chain
71 should set this to the address of a local variable. */
72 void *stack_top;
67 73
68 struct catchtag *m_catchlist; 74 struct catchtag *m_catchlist;
69#define catchlist (current_thread->m_catchlist) 75#define catchlist (current_thread->m_catchlist)