Subject: Re: bug#79306: Broken follow-mode

From: Stefan Monnier <[email-masked]>
Date: Thu, 04 Sep 2025 18:41:21 -0400

> I guess so (but we need a comment there explaining the reason for not
> calling dsafe_call).  And why didn't you bind inhibit_quit?

I just wanted to express the intent.

> One other thing we should perhaps consider: before you introduced the
> redisplay_counter thing, redisplay_internal would in this case return
> immediately at the beginning:
>
>   /* I don't think this happens but let's be paranoid.  In particular,
>      this was observed happening when Emacs shuts down due to losing X
>      connection, in which case accessing SELECTED_FRAME and the frame
>      structure is likely to barf.  */
>   if (redisplaying_p)
>     return;

Oh, very good point.
So maybe we just need the last two hunks below and the not the first.

        Stefan

diff --git a/src/xdisp.c b/src/xdisp.c
index 89561d750b6..763d9902486 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -14059,7 +14059,15 @@ prepare_menu_bars (void)
 		windows = Fcons (this, windows);
 	    }
 	}
-      dsafe_calln (true, Vpre_redisplay_function, windows);
+      {
+	/* We used to use 'dsafe_call' here, but actually we have not touched
+	   the redisplay state yet, so it's still safe to exit non-locally.  */
+	specpdl_ref count = SPECPDL_INDEX ();
+	specbind (Qinhibit_quit, Qt);
+	specbind (Qinhibit_redisplay, Qt);
+	calln (Vpre_redisplay_function, windows);
+	unbind_to (count, val);
+      }
     }
 
   /* Update all frame titles based on their buffer names, etc.  We do
@@ -17137,8 +17145,6 @@ 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).  */
@@ -17197,6 +17203,8 @@ redisplay_internal (void)
     return;
 #endif
 
+  redisplay_counter++;
+
   /* Record a function that clears redisplaying_p
      when we leave this function.  */
   specpdl_ref count = SPECPDL_INDEX ();