Subject: bug#78737: sit-for behavior changes when byte-compiled

From: Pip Cet <[email-masked]>
Date: Thu, 12 Jun 2025 13:58:51 +0000

"Daniel Colascione" <[email-masked]> writes:

> Eli Zaretskii <[email-masked]> writes:
>
>>> From: Daniel Colascione <[email-masked]>
>>> Cc: [email-masked],  [email-masked],  [email-masked]
>>> Date: Wed, 11 Jun 2025 07:08:45 -0700
>>>
>>> Why is it good that read-key-sequence swallows quits but not read-char?
>>
>> I don't know.  No one does.  maybe there's a good reason for it, maybe
>> there was one at some point but there isn't anymore, maybe it's just a
>> historical accident.
>>
>> But being unable to answer such questions doesn't mean changing the
>> behavior is safe.  It usually is the other way around, in a program as
>> old and complex as |Emacs.
>>
>>> C-g is an event.  Why should read-event (but not read-key-sequence?)
>>> translate one kind of input event (C-g) to an action (signal quit) but
>>> return other kinds of events as they're given?
>>
>> You consider this to be an inconsistency based only on the name of the
>> API.  But that's not necessarily the whole contract of the API.  It
>> doesn't need to be called get-char-quit-when-c-g to behave like it
>> does.
>>
>> Anyway, I think arguing about this aspect is not useful.  My problem
>> is not theoretical, it is practical: how much will break due to these
>> changes, and how long will it take us to become aware of the breakage
>> and attempt fixing it?
>
> I went through all the uses of read-char, read-char-exclusively, and
> read-event in the tree and didn't find anything that'll break if we make
> these functions return C-g as an event.  I did some things that worked

The first thing I looked at was mouse-drag-secondary.  It breaks (not
too badly: it just loses a quit event, but it's still an undesirable
change in behavior).

> marginally better, as I mentioned in my previous message.  It's possible
> something breaks, but I haven't seen evidence of breakage yet.

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?

> Yes, and for cases in which we're changing user-visible semantics in a
> way that'll break workflows --- like beginning-of-defun, perhaps ---
> then I agree with you.  I don't think this particular change belongs to
> that category.  I've looked for evidence that would change my mind and
> haven't found any yet.  You're right that changes to the input loop are
> risky, but they're going to be necessary sooner or later anyway, so
> wouldn't you prefer to change simpler code?

Since we've progressed to testing the branch, with the implication being
that we'll merge it soon, it may be too late to make alternative
suggestions.  In case it's not, though:

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.

That would simplify things, and give us a more powerful quit rather than
one subject to innocent mistakes in Lisp code that looks just fine.  The
"C-g quits" rule would simply take precedence over all other input
handling rules, simplifying the contract if that's what you think of it
as.

People who don't want quit to quit could then call (set-quit-char nil)
or something similar and reuse the quit character for something else.
Something like that should be the only way to disable this extremely
useful feature, though.

We could even make it the default behavior and let people who want quit
put it in their init files.

Independently of all this, we should change our triple C-g detection to
work in cases where a Lisp user or keyboard.c clears quit-flag without
actually handling the quit.  If we change things so C-g is ordinary
input, we can at least limit the damage and let people use triple C-g in
the unquittable infloops that will result (triple C-g isn't safe and you
should restart your Emacs session after using it, but that's less
inconvenient than losing the entire session).

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?

> Along the same lines, we could get rid of getcjmp too.  I'm not afraid
> of rationalizing the contract of read-event or tweaking any other part
> of keyboard.c, but that thing and quit_throw_to_read_char are extremely
> confusing and do scare me a bit --- all the more reason, in my mind, to
> get rid of them, like Gerd wanted to do years ago.  When is the right
> time to do that?  It's not like an Emacs 31 release is imminent.

I think that's a different discussion, to be honest.

getcjmp should be changed, definitely: it's currently updated
non-atomically using memcpy, which means we might longjmp to an
inconsistent jmp_buf from a signal handler and crash, IIUC.

Pip