Skip to content

Commit 8944310

Browse files
committed
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.
1 parent 8709aad commit 8944310

File tree

3 files changed

+4
-3
lines changed

3 files changed

+4
-3
lines changed

src/data.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1573,7 +1573,7 @@ notify_variable_watchers (Lisp_Object symbol,
15731573
/* Return the default value of SYMBOL, but don't check for voidness.
15741574
Return Qunbound if it is void. */
15751575

1576-
static Lisp_Object
1576+
Lisp_Object
15771577
default_value (Lisp_Object symbol)
15781578
{
15791579
struct Lisp_Symbol *sym;

src/eval.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3816,7 +3816,7 @@ backtrace_eval_unrewind (int distance)
38163816
{
38173817
Lisp_Object sym = specpdl_symbol (tmp);
38183818
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));
38203820
Fset_default (sym, old_value);
38213821
}
38223822
break;
@@ -3832,7 +3832,7 @@ backtrace_eval_unrewind (int distance)
38323832
if (!NILP (Flocal_variable_p (symbol, where)))
38333833
{
38343834
set_specpdl_old_value
3835-
(tmp, Fbuffer_local_value (symbol, where));
3835+
(tmp, buffer_local_value (symbol, where));
38363836
set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND);
38373837
}
38383838
}

src/lisp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ extern void char_table_set (Lisp_Object, int, Lisp_Object);
594594

595595
/* Defined in data.c. */
596596
extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object);
597+
extern Lisp_Object default_value (Lisp_Object symbol);
597598

598599

599600
/* Defined in emacs.c. */

0 commit comments

Comments
 (0)