From 70de5e86d84fc12c6115153c3d6276243cf2b995 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Tue, 5 Nov 2013 11:29:58 -0500 Subject: [PATCH] * src/eval.c (handlerlist_sentinel): New variable. (init_eval): Use it to ensure handlerlist is non-NULL. (unwind_to_catch): Make sure we never set handlerlist to NULL. (Fsignal): Adjust NULLness test of handlerlist. * src/lisp.h (PUSH_HANDLER): Assume handlerlist is non-NULL. Fixes: debbugs:15802 --- src/ChangeLog | 9 +++++++++ src/eval.c | 20 ++++++++++++++++++-- src/lisp.h | 5 ++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index e47f6a63740..e23af26f543 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2013-11-05 Stefan Monnier + + * eval.c (handlerlist_sentinel): New variable (bug#15802). + (init_eval): Use it to ensure handlerlist is non-NULL. + (unwind_to_catch): Make sure we never set handlerlist to NULL. + (Fsignal): Adjust NULLness test of handlerlist. + + * lisp.h (PUSH_HANDLER): Assume handlerlist is non-NULL. + 2013-11-05 Eli Zaretskii * callproc.c (call_process): Call prepare_to_modify_buffer before diff --git a/src/eval.c b/src/eval.c index a25dc1b5aa9..d3fcec5aef4 100644 --- a/src/eval.c +++ b/src/eval.c @@ -237,11 +237,22 @@ init_eval_once (void) Vrun_hooks = Qnil; } +static struct handler handlerlist_sentinel; + void init_eval (void) { specpdl_ptr = specpdl; - handlerlist = NULL; + { /* Put a dummy catcher at top-level so that handlerlist is never NULL. + This is important since handlerlist->nextfree holds the freelist + which would otherwise leak every time we unwind back to top-level. */ + struct handler *c; + handlerlist = handlerlist_sentinel.nextfree = &handlerlist_sentinel; + PUSH_HANDLER (c, Qunbound, CATCHER); + eassert (c == &handlerlist_sentinel); + handlerlist_sentinel.nextfree = NULL; + handlerlist_sentinel.next = NULL; + } Vquit_flag = Qnil; debug_on_next_call = 0; lisp_eval_depth = 0; @@ -1129,6 +1140,8 @@ unwind_to_catch (struct handler *catch, Lisp_Object value) { bool last_time; + eassert (catch->next); + /* Save the value in the tag. */ catch->val = value; @@ -1542,7 +1555,10 @@ See also the function `condition-case'. */) } else { - if (handlerlist != 0) + if (handlerlist != &handlerlist_sentinel) + /* FIXME: This will come right back here if there's no `top-level' + catcher. A better solution would be to abort here, and instead + add a catch-all condition handler so we never come here. */ Fthrow (Qtop_level, Qt); } diff --git a/src/lisp.h b/src/lisp.h index 863b0842f59..b70ca9e9f7c 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -2873,14 +2873,13 @@ struct handler /* Fill in the components of c, and put it on the list. */ #define PUSH_HANDLER(c, tag_ch_val, handlertype) \ - if (handlerlist && handlerlist->nextfree) \ + if (handlerlist->nextfree) \ (c) = handlerlist->nextfree; \ else \ { \ (c) = xmalloc (sizeof (struct handler)); \ (c)->nextfree = NULL; \ - if (handlerlist) \ - handlerlist->nextfree = (c); \ + handlerlist->nextfree = (c); \ } \ (c)->type = (handlertype); \ (c)->tag_or_ch = (tag_ch_val); \ -- 2.39.5