GNU bug report logs - #78737
sit-for behavior changes when byte-compiled

Previous Next

Package: emacs;

Reported by: Daniel Colascione <dancol <at> dancol.org>

Date: Mon, 9 Jun 2025 20:50:02 UTC

Severity: normal

Full log


View this message in rfc822 format

From: Pip Cet <pipcet <at> protonmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 78737 <at> debbugs.gnu.org, dancol <at> dancol.org, monnier <at> iro.umontreal.ca
Subject: bug#78737: sit-for behavior changes when byte-compiled
Date: Sat, 14 Jun 2025 07:55:54 +0000
"Eli Zaretskii" <eliz <at> gnu.org> writes:

>> Date: Fri, 13 Jun 2025 18:25:13 +0000
>> From: Pip Cet <pipcet <at> protonmail.com>
>> Cc: Eli Zaretskii <eliz <at> gnu.org>, dancol <at> dancol.org, 78737 <at> debbugs.gnu.org
>>
>> "Stefan Monnier" <monnier <at> iro.umontreal.ca> writes:
>>
>> >> What is a "normal quit"?
>> >
>> > A single C-g.
>> >
>> >> What is "emergency quit"?
>> >
>> > Something like `C-g C-g C-g`, tho we don't have that implemented,
>> > currently, AFAIK.
>>
>> It's implemented.  See handle_interrupt in keyboard.c:
>>
>>       /* Request quit when it's safe.  */
>>       int count = NILP (Vquit_flag) ? 1 : force_quit_count + 1;
>>       force_quit_count = count;
>>       if (count == 3)
>> 	Vinhibit_quit = Qnil;
>>       Vquit_flag = Qt;
>
> That's not "emergency quit", that's part of "emergency exit".  A
> different, though related, feature.

Sorry, still being dense.  This code is not reached on text terminals,
so it's not part of what trouble.texi calls the Emergency Escape
mechanism.  I thought you were using "emergency exit" to refer to the
Emergency Escape feature, but the above suggests that "emergency exit"
includes both the Emergency Escape and triple-C-g behavior on GUI
terminals.

I'd like a term for just the latter.

Triple C-g on a GUI terminal clears inhibit-quit and quits, breaking out
of loops such as:

(let ((inhibit-quit t))
  (while t))

This:

1. requires *three* C-g presses
2. does not trigger an Emergency Escape or exit Emacs
3. is unreachable on text terminals

Since this behavior does not exit Emacs, I thought it would not count as
part of the "emergency exit" feature.

>> The "emergency" part is clearing the inhibit-quit flag when
>> force_quit_count reaches 3.  The bug is that it should be >= 3, and the
>> questionable design feature is that we should reset the counter if
>> Vquit_flag and Vinhibit_quit are both nil, not just based on Vquit_flag.
>
> It isn't a bug, because emergency exit happens when the count is 2.

No, nothing special happens when the count reaches 2.

These two are mutually exclusive:

The code incrementing force_quit_count is unreachable on text terminals.

The code implementing the Emergency Escape feature is unreachable on GUI
terminals.

static void
handle_interrupt (bool in_signal_handler)
{
  char c;

  cancel_echoing ();

  /* XXX This code needs to be revised for multi-tty support.  */
  if (!NILP (Vquit_flag) && get_named_terminal (dev_tty))
    {
      <Emergency Escape feature>
    }
  else
    {
      <What do we call this?>
      /* Request quit when it's safe.  */
      int count = NILP (Vquit_flag) ? 1 : force_quit_count + 1; <-- on text terminals, Vquit_flag is nil!
      force_quit_count = count;
      if (count == 3)
	Vinhibit_quit = Qnil;
      Vquit_flag = Qt;
    }
  ...
}

So, on GUI frames, a double C-g will leave force_quit_count set to 2,
but it will not perform an Emergency Escape, and it will not clear
inhibit-quit.  Nothing special happens when force_quit_count reaches 2.

The third C-g, assuming quit-flag is still set, will clear inhibit-quit,
set the quit-flag again, and thus trigger a "special kind of quit".  I'm
looking for a name for it.

I note that this triple-C-g behavior is documented only in the code;
it's missing from trouble.texi.

diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi
index 45f15c7dd0d..33c97352f7c 100644
--- a/doc/emacs/trouble.texi
+++ b/doc/emacs/trouble.texi
@@ -83,6 +83,10 @@ Quitting
 actually executed as a command if you type it while Emacs is waiting for
 input.  In that case, the command it runs is @code{keyboard-quit}.
 
+  On graphical terminals, you may be able to quit by typing @kbd{C-g}
+three times, even when an ordinary @kbd{C-g} doesn't work.
+@xref{Feature X}.
+
   On a text terminal, if you quit with @kbd{C-g} a second time before
 the first @kbd{C-g} is recognized, you activate the emergency-escape
 feature and return to the shell.  @xref{Emergency Escape}.
@@ -157,7 +161,8 @@ Lossage
 * Memory Full::           How to cope when you run out of memory.
 * Crashing::              What Emacs does when it crashes.
 * After a Crash::         Recovering editing in an Emacs session that crashed.
-* Emergency Escape::      What to do if Emacs stops responding.
+* Feature X::             What to do if Emacs stops responding.
+* Emergency Escape::      What to do if Emacs stops responding on a text terminal.
 * DEL Does Not Delete::   What to do if @key{DEL} doesn't delete.
 @end menu
 
@@ -400,6 +405,22 @@ After a Crash
 which does not already exist; if the file does exist, the script does
 not make a backup of its old contents.
 
+@node Feature X
+@subsection Feature X
+@cindex feature x
+
+@c This works only if all terminals are graphical terminals; mixed
+@c text/GUI terminal sessions use the Emergency Escape feature.
+
+  On graphical terminals, typing @kbd{C-g} three times in a row while
+Emacs is not responding will clear the @code{inhibit-quit} flag.  This
+allows Emacs to recover from being stuck in certain kinds of loops.
+
+  After using this feature, Emacs will appear to have processed an
+ordinary quit, but you should exit and restart Emacs.  This is because
+forcibly clearing the @code{inhibit-quit} flag may have left Emacs in an
+inconsistent state.
+
 @node Emergency Escape
 @subsection Emergency Escape
 @cindex emergency escape

Obviously, we should replace "feature X" by something else.

Pip





This bug report was last modified 56 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.