Package: emacs;
Reported by: Daniel Colascione <dancol <at> dancol.org>
Date: Mon, 9 Jun 2025 20:50:02 UTC
Severity: normal
View this message in rfc822 format
From: Eli Zaretskii <eliz <at> gnu.org> To: Daniel Colascione <dancol <at> dancol.org> Cc: 78737 <at> debbugs.gnu.org, pipcet <at> protonmail.com, monnier <at> iro.umontreal.ca Subject: bug#78737: sit-for behavior changes when byte-compiled Date: Fri, 13 Jun 2025 14:34:06 +0300
> From: Daniel Colascione <dancol <at> dancol.org> > Cc: pipcet <at> protonmail.com, monnier <at> iro.umontreal.ca, 78737 <at> debbugs.gnu.org > Date: Fri, 13 Jun 2025 00:28:45 -0700 > > Eli Zaretskii <eliz <at> gnu.org> writes: > > >> From: Daniel Colascione <dancol <at> dancol.org> > >> Cc: Eli Zaretskii <eliz <at> gnu.org>, monnier <at> iro.umontreal.ca, > >> 78737 <at> debbugs.gnu.org > >> Date: Thu, 12 Jun 2025 11:48:50 -0700 > >> > >> Pip Cet <pipcet <at> protonmail.com> writes: > >> > >> > 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. > > > > We should start by agreeing that the capability of interrupting a > > running Lisp program is a real need. Are we in agreement about that? > > If not, let's first hear the arguments why not. > > Which Lisp programs? All of them. > One that calls (while t (read-event))? One that > calls (let ((inhibit-quit t)) (while t (read-event))? How about one > that calls (while t (read-key-sequence ""))? How about one that calls > (let ((inhibit-quit t)) (while t (read-key-sequence ""))? If you adopt > the tenet that Lisp programs always be uninterruptible, _something_ has > to change from the present, because 3/4 of my examples above cannot > be quit. So because we currently cannot interrupt some programs we should give up the ability to interrupt all of them? Please be serious. Arguments like the above are a red herring, and don't help advancing this discussion towards some kind of agreement. Do you want the branch merged at some point? Then please drop the attitude and start participating in the discussion seriously. You understand very well what I meant above, even though it is somewhat vague. We all know what Emacs can and cannot do today, so I allow myself not to write too many well-known details. Let's consider the current capabilities of interrupting Lisp programs as base line, and try to maintain that base line, if not improve on it. Okay? Or does it still not satisfy your intentionally-pedantic interpretation of what I write? > > If we _are_ in agreement about that, we should discuss how this should > > be possible if read-event (and perhaps others?) return C-g instead of > > raising quit-flag. The alternatives mentioned until now are: > > > > . restore the old behavior, whereby C-g interrupts read-event > > Does not satisfy the "lisp programs always be > interruptible" requirement. > > > . have a variable that, if set, will restore the old behavior in > > Same as above. > > > read-event and other affected primitives, to be interruptible by a > > single C-g > > Same as above. Please reconsider your responses with a more serious and cooperative attitude. > > . make two C-g presses "in quick succession" set quit-flag, IOW > > "C-g C-g" will have the same effect as C-g previously > > Only for read-event. Why "only"? Having the behavior vary depending on whether the program does or doesn't call read-event will bring inconsistency, something we want to avoid (and which I think you argued against). > If you want to adopt a principled stance that every Lisp program be > interruptible, you necessarily, as a matter of logic, regard multiple > behaviors of current Emacs to be bugs worth fixing. Not useful. I didn't mean that, and you know it. > > Are there other alternatives? > > Get in a time machine, go back 40 years and stop overloading C-g? Even less useful. Again, do you want this branch to be merged any time soon? Because I'm this close to losing my patience. Life's too short to waste it on "arguments" such as this one. > > I don't think there's disagreement on that level. So let's drop this > > kind of arguments, because they are not useful for this discussion. > > The problem we face is how to allow Lisp code to be quittable. A Lisp > > program that calls read-event is not different from a Lisp program > > calling any other function, so we still need such programs to be > > quittable somehow. Let's discuss how best to do it, okay? > > Yes or no: should (while t (read-key-sequence)) be quittable? Why is that relevant? I asked about read-event, not read-key-sequence. Can we first discuss the read-event case? Once we are done with that, we can move to other cases. > If yes, maintaining today's behavior isn't an option. There are plenty > of other Lisp programs that cannot be quit --- even (let ((inhibit-quit > t)) (while t)) cannot be quit! If inhibit-quit is bound to a non-nil value, the program cannot be quit, and that's a feature. Why are we discussing this? > If no, what is the problem with cleaning up Emacs by regularizing how we > treat C-g as an event versus some kind of longjmp? Again, let's discuss the read-key-sequence case after we are done with the read-event case. > >> > 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. > > > > This is the last alternative I described above. It is IMO less > > desirable, because it is not always easy to press C-g twice quickly, > > for whatever reasons. It is even less desirable to define "quick > > succession" in terms of time, because timings can differ a lot > > depending on the free computing resources and the CPU power in > > general, so determining the best default values will be very > > challenging, to say the least. > > I don't see the ambiguity being a realistic problem. How often do you > press C-g three times while a single command is running? I usually expect a single C-g to quit. If it doesn't help, I can press C-g several times, I'm not sure I count them. > We're not talking about, say, six times in multiple rounds of M-x this, > select that, deactivate mark over here. Those are multiple commands. > In between multiple commands, a C-g will cause a keyboard-quit and > you'll regain control over Emacs. I'm asking, during _one_ command, how > many times you typically press C-g and _don't_ mean it as a quit. See above. > We already have a force quit mechanism that kicks in at N=3. How often > do you activate it? I never saw it at work, except on TTY frames. But then Windows doesn't have SIGIO, it emulates that. Maybe that's the reason. > >> On your Emacs, you can set N to one and T to zero. > > > > If read-event still returns a keyboard input event when C-g is > > pressed, I don't see how N = 1 would work. Can you describe how it > > would work? > > It wouldn't. Such a setting would prevent read-input returning C-g. > That shouldn't be the default. Sorry, I don't understand. If N = 1, what will read-event do when the user presses C-g while inside read-event? Will it return the input event C-g, or will it quit? I thought your changes make read-event always return the input event, was I mistaken? > >> 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? > > > > Why not? If it helps debugging, we could definitely do that. We > > already have --enable-checking, which changes how some primitives > > work, in a very real sense. As long as the feature is for debugging > > Emacs, anything useful goes, IMO. > > Because when you add a user option, people expect code you write to > operate under any value of that option, increasing implementation > complexity because you have to account for the _possibility_ someone > might operate in a certain way. No, people need not expect the code to operate the same under those special debugging-oriented values. We already have such features: debug-on-error = t might well cause some command cease working normally, and similarly condition-case-unless-debug. So I think you are bothered by a problem that doesn't need to be solved. > >> >>> 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. > > > > I'm skeptical that we will be able to count C-g presses so as to > > reliably differentiate between double or triple press and two or three > > separate C-g presses. > > There is logically no difference between these two concepts. A double > keypress *is* two keypresses in a certain window of time. What other > concept could the combination of the words "double" and "press" convey? I don't understand what you are saying here. Yes, there's no logical difference between these, which is why I'm saying that reliably detecting "double C-g" is a challenge. We already have that with double-mouse. The difference between double-mouse and "double C-g" is that with the latter you cannot afford low reliability: when you want to quit, you want to do it immediately, because the runaway operation you want to interrupt could be harmful. > > Different machines and OSes, and different > > system loads, can make it nigh impossible to do reliably. And that's > > _bad_, because when I want something interrupted right away, I don't > > want or even cannot try again and again and again until it works. > > Then define a separate key that means _only_ quit and that cannot be > bound to a regular command. C-g can't be that command without breaking > existing code. It's too late to define a separate key _instead_ of C-g. We could define a separate key _in_addition_ to C-g, but that doesn't solve the problem: people have C-g hardwired into their muscle memory, and it will take a lot of time for them to re-learn. Meanwhile, we get bug reports about C-g not working like it did before. So minimizing the behavior changes is still a requirement, even if we add another key. And that's before we even consider what other key could serve that purpose, which is not a trivial problem to solve portably. > Treating repeated C-g presses made in a reasonable window of time within > the scope of a single command in such a way that we're almost certainly > not confusing this series of keystrokes with C-g-as-command input solves > the problem. That's possible, but it is not the best alternative IMO, for the reasons I explained.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.