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

From: Daniel Colascione <[email-masked]>
Date: Thu, 12 Jun 2025 07:35:51 -0700

Pip Cet <[email-masked]> writes:

> "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).

Recipe?  mouse-drag-secondary seems to be working all right for me, but
I never use the feature in anger so I might be missing something.

>> 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?

No worse than calling read-key-sequence.

>> 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.

Lisp can quit just fine.  What are you talking about?

> 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.

C-g is an event.  The quit mechanism is a low-level mechanism for
breaking out of Lisp code in response to this event.  It makes no sense
one key on the keyboard with longjmp when we use a value for the two
keys next to it.  When code says it wants an event, it should get an
event.  That we interpret this event to mean quit in other circumstances
doesn't mean it's no longer an event.

> 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.

I don't believe it's easier if we handle all keyboard events except one
by returning a value but longjmp on this one special one.

> 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.

Huh?  Nobody's disabling quit.

> 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).

Have you gotten your branches mixed up?  You seem to be ranting about a
set of patches with little resemblance to the ones we're discussing.
The branch we're talking about doesn't stop C-g quitting Lisp.

> 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.

We don't jump in signal handlers for input.  If we did, we'd have much
bigger problems.  when's the last time you read keyboard.c?
handle_input_available_signal doesn't jump anywhere.