emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

emacs-27 8944310 3/3: Don't signal during backtrace unrewind (Bug#40088)


From: Noam Postavsky
Subject: emacs-27 8944310 3/3: Don't signal during backtrace unrewind (Bug#40088)
Date: Sun, 22 Mar 2020 23:13:45 -0400 (EDT)

branch: emacs-27
commit 8944310d7c9e259c9611ff2f0004c3176eb0ddab
Author: Noam Postavsky <address@hidden>
Commit: Noam Postavsky <address@hidden>

    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.
---
 src/data.c | 2 +-
 src/eval.c | 4 ++--
 src/lisp.h | 1 +
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/data.c b/src/data.c
index b153068..5ce5e36 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1573,7 +1573,7 @@ notify_variable_watchers (Lisp_Object symbol,
 /* Return the default value of SYMBOL, but don't check for voidness.
    Return Qunbound if it is void.  */
 
-static Lisp_Object
+Lisp_Object
 default_value (Lisp_Object symbol)
 {
   struct Lisp_Symbol *sym;
diff --git a/src/eval.c b/src/eval.c
index 4559a0e..78a787c 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3816,7 +3816,7 @@ backtrace_eval_unrewind (int distance)
          {
            Lisp_Object sym = specpdl_symbol (tmp);
            Lisp_Object old_value = specpdl_old_value (tmp);
-           set_specpdl_old_value (tmp, Fdefault_value (sym));
+           set_specpdl_old_value (tmp, default_value (sym));
            Fset_default (sym, old_value);
          }
          break;
@@ -3832,7 +3832,7 @@ backtrace_eval_unrewind (int distance)
            if (!NILP (Flocal_variable_p (symbol, where)))
              {
                set_specpdl_old_value
-                 (tmp, Fbuffer_local_value (symbol, where));
+                 (tmp, buffer_local_value (symbol, where));
                 set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND);
              }
          }
diff --git a/src/lisp.h b/src/lisp.h
index 8674fe1..92294ac 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -594,6 +594,7 @@ extern void char_table_set (Lisp_Object, int, Lisp_Object);
 
 /* Defined in data.c.  */
 extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object);
+extern Lisp_Object default_value (Lisp_Object symbol);
 
 
 /* Defined in emacs.c.  */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]