Package: emacs;
Reported by: Daniel Colascione <dancol <at> dancol.org>
Date: Mon, 9 Jun 2025 20:50:02 UTC
Severity: normal
Message #137 received at 78737 <at> debbugs.gnu.org (full text, mbox):
From: Daniel Colascione <dancol <at> dancol.org> To: Pip Cet <pipcet <at> protonmail.com> Cc: 78737 <at> debbugs.gnu.org, Eli Zaretskii <eliz <at> gnu.org>, monnier <at> iro.umontreal.ca Subject: Re: bug#78737: sit-for behavior changes when byte-compiled Date: Thu, 12 Jun 2025 11:48:50 -0700
Pip Cet <pipcet <at> protonmail.com> writes: > "Eli Zaretskii" <eliz <at> gnu.org> writes: > >>> Date: Thu, 12 Jun 2025 13:58:51 +0000 >>> From: Pip Cet <pipcet <at> protonmail.com> >>> Cc: Eli Zaretskii <eliz <at> gnu.org>, monnier <at> iro.umontreal.ca, 78737 <at> debbugs.gnu.org >>> >>> I'd say breaking (read-event) called in a loop is bad enough, because >>> how else are you supposed to start developing code which uses it? >> >> Maybe this regression should be fixed, then. > > I agree it should be, if we can agree it is a regression; the other > issues I see are SIGUSR2 handling (which seems fixable) and the question > of whether saving unhandled events in unread-command-events is always > the right choice. > >>> I think this discussion is concerned too much with what existing code >>> will break if we change quit not to quit, not enough with how much more >>> difficult it will be to develop code if we do, and not at all, so far, >>> with what the advantages of handling quit in Lisp (if Lisp decides to >>> handle it at all) are. >>> >>> C-g isn't an input event in the same way that kicking someone in the >>> shin is not a dance move. I want it to kick Emacs in the shin, and >>> break out of bad Lisp code, in *more* situations than it does now. >> >> Please describe the situations where you'd like it to throw to top >> level and it doesn't now. > > One situation for ordinary quits; three for force-quit. > > Situation 1: > > I'd like read-event, when called while inhibit-quit is t, to report > quits by setting quit-flag in addition to returning quit_char: it'll > simplify the C code, and it would make > > (while t > (let ((inhibit-quit t)) > (read-event))) I strongly disagree. read-event should read an event. Setting quit-flag by side effect when it happens to read one key and not others makes the interface less regular and understandable. read-key-sequence is the high-level function. read-event is the low-level function. It makes zero sense for the high-level function to report a key event as a low-level event and for the low-level function to do special non-local flow control in response to that event. > quittable, as I naively expected it to be. The naive expectation is that this function do its job. > The old behavior would > remain available, but require an extra let binding. > > Note that this isn't > > (let ((inhibit-quit t)) > (while t > (read-event))) Then fix read-key-sequence, which acts the same way. > While I'd like to change the C code to make this second case > force-quittable, I see no way to perform an ordinary quit for this code. > The reason I mention it is that removing > > /* If we report the quit char as an event, > don't do so more than once. */ > if (!NILP (Vinhibit_quit)) > Vquit_flag = Qnil; > > changes behavior for both loops: the first becomes quittable, the second > becomes force-quittable. There is no reason for these loops to behave differently. If we want to make both force-quittable, as I described in https://lists.gnu.org/archive/html/bug-gnu-emacs/2025-06/msg00629.html, but an ordinary press of C-g should not cause a quit when Lisp has explicitly asked to read an event by calling a function whose job it is to read events. > Situation 2: > > (while t > (read-key-sequence "")) > > It'd be nice for this situation to be force-quittable; I don't see why > it shouldn't be, even though what I implemented is a bit of a hack... > > Situation 3: > > Several force-quits in the same session. Reset force_quit_count to 0 > once it reaches 3. I've seen force_quit_count reach higher values than > 3 (there was no regular quit in between force quit attempts). Get rid of force_quit_count entirely and just detect (by writing into a ring buffer) whether we've received N quits in the last T milliseconds. That'll work the same way regardless of how quits gets detected. We can change N and T freely. On your Emacs, you can set N to one and T to zero. >> Also, can this behavior be optional, like debug-on-error and friends >> are? Not everyone debugs Lisp code all the time, so we definitely can >> have an "easy-break-out" feature that is by default off. > Absolutely. We could easily make it customizable whether read-event > sets quit-flag after a quit: > > 1. never > 2. only when !inhibit-quit > 3. always We can customize thresholds for general behavior, but I don't think we should not have preferences that alter the operation of fundamental Emacs primitives. You couldn't add a preference that made if regard 0 as well as nil as false, would you? >>> Maybe a compromise would be to continue the arms race and downgrade C-g >>> to normal input, C-g C-g C-g to a quit, and require even more C-g's for >>> a force-quit? >> >> That's also possible, though less desirable: counting C-g presses when >> you are desperate is not easy and we cannot rely on users to do that >> reliably. > > And we'd need a way to detect when a quit is handled (however we define > "handled") so we could reset force_quit_counter. Not a trivial change. You don't. You just upgrade any quit that happens under the N and T threshold above.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.