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


Message #308 received at 78737 <at> debbugs.gnu.org (full text, mbox):

From: Pip Cet <pipcet <at> protonmail.com>
To: Lynn Winebarger <owinebar <at> gmail.com>
Cc: 78737 <at> debbugs.gnu.org, Eli Zaretskii <eliz <at> gnu.org>,
 Daniel Colascione <dancol <at> dancol.org>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#78737: sit-for behavior changes when byte-compiled
Date: Sat, 14 Jun 2025 06:28:06 +0000
"Lynn Winebarger" <owinebar <at> gmail.com> writes:

> On Fri, Jun 13, 2025 at 10:02 AM Daniel Colascione <dancol <at> dancol.org> wrote:
>>
>>
>>
>> On June 13, 2025 6:42:58 AM PDT, Daniel Colascione <dancol <at> dancol.org> wrote:
>> >
>> >
>> >On June 13, 2025 5:23:34 AM PDT, Lynn Winebarger <owinebar <at> gmail.com> wrote:
>> >>On Fri, Jun 13, 2025, 2:26 AM Eli Zaretskii <eliz <at> gnu.org> wrote:
>> >>
>> >>> > 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.
>> >>>
>> >>> 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
>> >>>  . have a variable that, if set, will restore the old behavior in
>> >>>    read-event and other affected primitives, to be interruptible by a
>> >>>    single C-g
>> >>>  . 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
>> >>>
>> >>> Are there other alternatives?
>> >>>
>> >>
>> >>What about keeping a (possibly buffer-local?) lisp variable holding a list
>> >>of keystrokes mapped to thunks that are treated as generating lisp machine
>> >>"interrupts"?  The key strokes would be processed by C machinery and never
>> >>seen directly by lisp code and not be considered "events".
>> >>Then C-g could be bound to a thunk signalling quit, and the effect of
>> >>"inhibit-quit" achieved by removing C-g from the list in a given dynamic
>> >>scope.  Then user code could make other key-strokes "special" without
>> >>resorting to read-event.  For example, this read-event call in term.el:
>> >>(message "Hit space to flush")
>> >>      (let ((ch (read-event)))
>> >> (if (eq ch ?\s)
>> >>     (set-window-configuration conf)
>> >>   (push ch unread-command-events)))
>> >>
>> >>Could be replaced by something like
>> >>(with-interrupts ((?\s (signal term-flush)))
>> >>  (condition-case nil
>> >>    (while t (sit-for 100))
>> >>     (term-flush (set-window-configuration conf))))
>> >>
>> >>Then some of these use-case concerns could be mooted altogether.
>> >
>> >We already have something like that. :-) read-event already runs
>> > the events it reads through special-event-map, right? We don't
>> > even need to create a separate thunk list concept: we could just
>> > bind C-g in special event map and do what we want, right?

> Would that provide the behavior Pip is looking for?

It would not, because quits are currently processed out-of-order, and
this important feature should remain in place for "serious" quits.  See
below.

>> >The only special thing about C-g is how we treat it when Lisp is
>> > running. When it's instead reading an event, it can and be a
>> > boring event processed the same way every other event is.

> It seems to me what Pip is looking for is analogous to a "Quit" button
> hardwired to a pin on a CPU, which is not something that can be
> reliably implemented in the C primitives as they are now.

You're suggesting I'm looking for something that cannot be implemented.
I'm not.

I described specific situations in which I think quit should be expanded
to work better than it does now.  No one's expecting that quit works in
absolutely every situation, as far as I know.  That's what gdb is for.

If you're referring to the "C-g C-g" thing, I did not describe how I'd
implement it in detail, because there are many choices to be made; but
the main idea would be that we should not immediately clear inhibit-quit
for that combination, because that's a dangerous and destructive thing
to do.  If we decide to do so (after a delay, for example), we need to
print a clear warning to the user that their Emacs session needs
restarting.

So C-g C-g might do less than GUI C-g C-g C-g does currently.

There are actions even more dangerous than clearing inhibit-quit.  I
don't know whether we want a level-3 quit which does even more than the
current GUI C-g C-g C-g code.

But, again, such decisions ultimately require actually writing code, and
I haven't, so far.

> It would also mean a C-g (or other designated interrupt) could be
> processed earlier than preceding keystrokes, but that seems like what
> Pip would want?

That's the current behavior.  I'd like to keep it.

Quit has some immediate effects, including sometimes clearing
unread-command-events, discarding queued input.  It also sets the quit
flag before other input is processed.  It then causes an actual quit,
which is an error, which causes Fdiscard_input to be called.

>> Oh yeah, one thing I forgot to mention: for the *asynchronous* case,
>> the C code is pretty deeply coupled to quit_char, and IIRC, even
>> hard codes 7, C-g, in some places instead of quit_char. In your
>> proposal, we'd references to quit_char and literal 7 to calls to a
>> new bool is_quit_char(int c) function -- and this function would
>> return true for any raw keys bound in special-event-map. In this
>> way, you'd be able to define as many asynchronous-input characters
>> as you wanted.
> I guess I would consider removing that kind of hard-coded logic a
> plus?

I think whether to make quit_char configurable (in GUI sessions) or keep
the code which makes it configurable (in terminal sessions only) is a
very minor detail.

This comment in bindings.el:

;; The following wouldn't work to interrupt running code since C-g is
;; treated specially in the event loop.
;; (define-key global-map [stop]		'keyboard-quit) ; Sun

suggests someone once wanted to add an additional quit_char and gave up.

Pip





This bug report was last modified 55 days ago.

Previous Next


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