diff options
| author | Noam Postavsky | 2020-03-20 04:07:39 -0400 |
|---|---|---|
| committer | Noam Postavsky | 2020-03-22 23:06:31 -0400 |
| commit | 8944310d7c9e259c9611ff2f0004c3176eb0ddab (patch) | |
| tree | 13a0f17f063ecb83481f94166ba7f68b19beeba2 | |
| parent | 8709aaddd8707c9eafb359f9ec824e4bc109bbc6 (diff) | |
| download | emacs-8944310d7c9e259c9611ff2f0004c3176eb0ddab.tar.gz emacs-8944310d7c9e259c9611ff2f0004c3176eb0ddab.zip | |
Don't signal during backtrace unrewind (Bug#40088)
backtrace_eval_unrewind is used to temporarily reverse
let-bindings (it's called with a positive argument to reverse
bindings, and then a negative argument to re-apply them) by
backtrace--locals and backtrace-eval. For the SPECPDL_LET_DEFAULT and
SPECPDL_LET_LOCAL cases (which occur for let-bindings on buffer-local
variables), the code calls Fdefault_value and Fbuffer_local_value on
the symbol.
For symbols which are unbound at top-level, the first (with positive
argument) call to backtrace_eval_unrewind will set the symbol's value
to unbound (putting the current value in the specpdl's "old value"
slot). On the second (with negative argument) call,
backtrace_eval_unrewind attempts to retrieve the symbol's value with
Fdefault_value or Fbuffer_local_value, but that raises a void-variable
signal. This interrupts the restoration of the let-bindings, so any
other variables more recent on the stack will now have the wrong
value.
* src/data.c (default_value): Make non-static.
* src/lisp.h: Declare it.
* src/eval.c (backtrace_eval_unrewind): Replace the calls to
Fdefault_value and Fbuffer_local_value with default_value and
buffer_local_value, respectively. The latter do exactly the same as
the former, except if the symbol's value is Qunbound they just return
it instead of signaling void-variable.
| -rw-r--r-- | src/data.c | 2 | ||||
| -rw-r--r-- | src/eval.c | 4 | ||||
| -rw-r--r-- | src/lisp.h | 1 |
3 files changed, 4 insertions, 3 deletions
diff --git a/src/data.c b/src/data.c index b1530688468..5ce5e360ab4 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -1573,7 +1573,7 @@ notify_variable_watchers (Lisp_Object symbol, | |||
| 1573 | /* Return the default value of SYMBOL, but don't check for voidness. | 1573 | /* Return the default value of SYMBOL, but don't check for voidness. |
| 1574 | Return Qunbound if it is void. */ | 1574 | Return Qunbound if it is void. */ |
| 1575 | 1575 | ||
| 1576 | static Lisp_Object | 1576 | Lisp_Object |
| 1577 | default_value (Lisp_Object symbol) | 1577 | default_value (Lisp_Object symbol) |
| 1578 | { | 1578 | { |
| 1579 | struct Lisp_Symbol *sym; | 1579 | struct Lisp_Symbol *sym; |
diff --git a/src/eval.c b/src/eval.c index 4559a0e1f66..78a787c4ffd 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -3816,7 +3816,7 @@ backtrace_eval_unrewind (int distance) | |||
| 3816 | { | 3816 | { |
| 3817 | Lisp_Object sym = specpdl_symbol (tmp); | 3817 | Lisp_Object sym = specpdl_symbol (tmp); |
| 3818 | Lisp_Object old_value = specpdl_old_value (tmp); | 3818 | Lisp_Object old_value = specpdl_old_value (tmp); |
| 3819 | set_specpdl_old_value (tmp, Fdefault_value (sym)); | 3819 | set_specpdl_old_value (tmp, default_value (sym)); |
| 3820 | Fset_default (sym, old_value); | 3820 | Fset_default (sym, old_value); |
| 3821 | } | 3821 | } |
| 3822 | break; | 3822 | break; |
| @@ -3832,7 +3832,7 @@ backtrace_eval_unrewind (int distance) | |||
| 3832 | if (!NILP (Flocal_variable_p (symbol, where))) | 3832 | if (!NILP (Flocal_variable_p (symbol, where))) |
| 3833 | { | 3833 | { |
| 3834 | set_specpdl_old_value | 3834 | set_specpdl_old_value |
| 3835 | (tmp, Fbuffer_local_value (symbol, where)); | 3835 | (tmp, buffer_local_value (symbol, where)); |
| 3836 | set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND); | 3836 | set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND); |
| 3837 | } | 3837 | } |
| 3838 | } | 3838 | } |
diff --git a/src/lisp.h b/src/lisp.h index 8674fe11a64..92294ac1d33 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -594,6 +594,7 @@ extern void char_table_set (Lisp_Object, int, Lisp_Object); | |||
| 594 | 594 | ||
| 595 | /* Defined in data.c. */ | 595 | /* Defined in data.c. */ |
| 596 | extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object); | 596 | extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object); |
| 597 | extern Lisp_Object default_value (Lisp_Object symbol); | ||
| 597 | 598 | ||
| 598 | 599 | ||
| 599 | /* Defined in emacs.c. */ | 600 | /* Defined in emacs.c. */ |