emacs-diffs
[Top][All Lists]
Advanced

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

scratch/handler-bind-2 235907e1764 12/16: Add `redisplay-counter` to cat


From: Stefan Monnier
Subject: scratch/handler-bind-2 235907e1764 12/16: Add `redisplay-counter` to catched nested redisplays and abort outer one
Date: Wed, 27 Dec 2023 23:53:31 -0500 (EST)

branch: scratch/handler-bind-2
commit 235907e17647f2cb924de759bfaca88eb0a35e08
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 a821312b5ff..7bb26abc616 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -304,14 +304,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 aa1d4433914..551887e9207 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);
     }
 
@@ -16663,6 +16681,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]