diff options
| author | Stefan Monnier | 2013-11-05 11:29:58 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2013-11-05 11:29:58 -0500 |
| commit | 70de5e86d84fc12c6115153c3d6276243cf2b995 (patch) | |
| tree | ef217abb628c34bf0f8af42bf866c56419f95953 /src/eval.c | |
| parent | 03177f98c9c755b98e25ad9c51bd4945798e77e4 (diff) | |
| download | emacs-70de5e86d84fc12c6115153c3d6276243cf2b995.tar.gz emacs-70de5e86d84fc12c6115153c3d6276243cf2b995.zip | |
* 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
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 20 |
1 files changed, 18 insertions, 2 deletions
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) | |||
| 237 | Vrun_hooks = Qnil; | 237 | Vrun_hooks = Qnil; |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | static struct handler handlerlist_sentinel; | ||
| 241 | |||
| 240 | void | 242 | void |
| 241 | init_eval (void) | 243 | init_eval (void) |
| 242 | { | 244 | { |
| 243 | specpdl_ptr = specpdl; | 245 | specpdl_ptr = specpdl; |
| 244 | handlerlist = NULL; | 246 | { /* Put a dummy catcher at top-level so that handlerlist is never NULL. |
| 247 | This is important since handlerlist->nextfree holds the freelist | ||
| 248 | which would otherwise leak every time we unwind back to top-level. */ | ||
| 249 | struct handler *c; | ||
| 250 | handlerlist = handlerlist_sentinel.nextfree = &handlerlist_sentinel; | ||
| 251 | PUSH_HANDLER (c, Qunbound, CATCHER); | ||
| 252 | eassert (c == &handlerlist_sentinel); | ||
| 253 | handlerlist_sentinel.nextfree = NULL; | ||
| 254 | handlerlist_sentinel.next = NULL; | ||
| 255 | } | ||
| 245 | Vquit_flag = Qnil; | 256 | Vquit_flag = Qnil; |
| 246 | debug_on_next_call = 0; | 257 | debug_on_next_call = 0; |
| 247 | lisp_eval_depth = 0; | 258 | lisp_eval_depth = 0; |
| @@ -1129,6 +1140,8 @@ unwind_to_catch (struct handler *catch, Lisp_Object value) | |||
| 1129 | { | 1140 | { |
| 1130 | bool last_time; | 1141 | bool last_time; |
| 1131 | 1142 | ||
| 1143 | eassert (catch->next); | ||
| 1144 | |||
| 1132 | /* Save the value in the tag. */ | 1145 | /* Save the value in the tag. */ |
| 1133 | catch->val = value; | 1146 | catch->val = value; |
| 1134 | 1147 | ||
| @@ -1542,7 +1555,10 @@ See also the function `condition-case'. */) | |||
| 1542 | } | 1555 | } |
| 1543 | else | 1556 | else |
| 1544 | { | 1557 | { |
| 1545 | if (handlerlist != 0) | 1558 | if (handlerlist != &handlerlist_sentinel) |
| 1559 | /* FIXME: This will come right back here if there's no `top-level' | ||
| 1560 | catcher. A better solution would be to abort here, and instead | ||
| 1561 | add a catch-all condition handler so we never come here. */ | ||
| 1546 | Fthrow (Qtop_level, Qt); | 1562 | Fthrow (Qtop_level, Qt); |
| 1547 | } | 1563 | } |
| 1548 | 1564 | ||