emacs-diffs
[Top][All Lists]
Advanced

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

scratch/handler-bind 071ea552e6b 10/12: Add `redisplay-counter` to catch


From: Stefan Monnier
Subject: scratch/handler-bind 071ea552e6b 10/12: Add `redisplay-counter` to catched nested redisplays and abort outer one
Date: Mon, 25 Dec 2023 23:56:51 -0500 (EST)

branch: scratch/handler-bind
commit 071ea552e6b8f3b0791bd7b7c5d672f760bd14e9
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>

    Add `redisplay-counter` to catched nested redisplays and abort outer one
---
 src/eval.c  |  8 --------
 src/xdisp.c | 22 +++++++++++++++++++++-
 2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/src/eval.c b/src/eval.c
index b2b110da15b..ec98d00a725 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -314,14 +314,6 @@ call_debugger (Lisp_Object arg)
 
   val = apply1 (Vdebugger, arg);
 
-  /* Interrupting redisplay and resuming it later is not safe under
-     all circumstances.  So, when the debugger returns, abort the
-     interrupted redisplay by going back to the top-level.  */
-  /* FIXME: Move this to the redisplay code?  */
-  if (debug_while_redisplaying
-      && !EQ (Vdebugger, Qdebug_early))
-    Ftop_level ();
-
   return unbind_to (count, val);
 }
 
diff --git a/src/xdisp.c b/src/xdisp.c
index 2a979c5cb9e..b711987b8c3 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3031,6 +3031,17 @@ hscrolling_current_line_p (struct window *w)
                        Lisp form evaluation
  ***********************************************************************/
 
+/* The redisplay is not re-entrant.  But we can run ELisp code during
+   redisplay, which in turn can trigger redisplay.
+   We try to make this inner redisplay work correctly, but it messes up
+   the state of the outer redisplay, so when we return to this outer
+   redisplay, we need to abort it.
+   To dect this case, we keep a counter that identifies every call to the
+   redisplay, so we can detect when a nested redisplay happened by the
+   fact that the counter has changed.  */
+
+static int redisplay_counter = 0;
+
 /* Error handler for dsafe_eval and dsafe_call.  */
 
 static Lisp_Object
@@ -3062,10 +3073,17 @@ dsafe__call (bool inhibit_quit, Lisp_Object (f) 
(ptrdiff_t, Lisp_Object *),
       specbind (Qinhibit_redisplay, Qt);
       if (inhibit_quit)
        specbind (Qinhibit_quit, Qt);
+      int redisplay_counter_before = redisplay_counter;
       /* Use Qt to ensure debugger does not run,
-        so there is no possibility of wanting to redisplay.  */
+        to reduce the risk of wanting to redisplay.  */
       val = internal_condition_case_n (f, nargs, args, Qt,
                                       dsafe_eval_handler);
+      if (redisplay_counter_before != redisplay_counter)
+        /* A nested redisplay happened, abort this one!  */
+        /* FIXME: Rather than jump all the way to to `top-level`
+           we should exit only the current redisplay.  */
+        Ftop_level ();
+
       val = unbind_to (count, val);
     }
 
@@ -16649,6 +16667,8 @@ redisplay_internal (void)
   bool polling_stopped_here = false;
   Lisp_Object tail, frame;
 
+  redisplay_counter++;
+
   /* Set a limit to the number of retries we perform due to horizontal
      scrolling, this avoids getting stuck in an uninterruptible
      infinite loop (Bug #24633).  */



reply via email to

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