Subject: Re: 28.0.50; process-send-string mysteriously exiting non-locally when called from timer

From: João Távora <[email-masked]>
Date: Thu, 10 Dec 2020 18:50:33 +0000

Stefan Monnier <[email-masked]> writes:

>> I'm not sure.  Every such async system eventually boils down
>> to a point that sends something to the wire (step A) and a process
>> filter (step C) that runs later on and finds some suitable "continuation",
>> (a callback).
>
> [ I'm not completely sure I understand your scenario above, so we may
>   be miscommunicating.  ]
>
> Right.  And `while-no-input` should only wrap the execution of A, so if
> A doesn't complete, then presumably none of C nor B will want to be
> executed, which seems OK.

We are miscommunicating.  In these programs, B needs to be atomic with
A.  When you send things into an external process, only the most naive
of external communication protocol replies immediately and synchronously
to the thing you just sent.  For those super simple things, like "cat"
and "grep", your model works.

But a complex multi-threaded program being talked to via the network,
will process requests it is fed through the wire in varying rates and
rythms.  So you need system in the Elisp side that decodes what async
request the process is responding to.  See jsonrpc.el's
jsonrpc-connection-receive, for instance.

> closes the pipe in case we're exiting before having sent all the data
> (that's a good idea to do also in case a bug signals an error).

Again, this killing of the subprocess assumes the trivial case of a unix
utility.

>> Actually, thinking more about it. I don't think it's sound to have a
>> while-no-input at all under library control.  A programmer using
>> that library should be given a predictable evaluation model.  At
>> any rate, this is a regression from 26.3, where things didn't work
>> like this.
>
> The exact same problem affects all normal Elisp code when the user hits
> C-g, so I think the better path forward is to make sure it's "easy and
> natural" to write code which reacts correctly when it's aborted at some
> arbitrary time.  We usually get that via `unwind-protect`, but if it's
> not enough we should develop better solutions rather than shy away from
> `quit`.

I get what you're saying, but there's a presumably reason we bind
inhibit-quit to t in timers (Eli?), and it's that that code isn't
triggered by a direct action of he user.  Indeed in idle timers, it's
triggered by the _inaction_ of the user.  So it makes no sense to also
use that allow quitting model there, unless the programmer of the timer
function expects to do something very lengthy, whereup he should
consciously turn it off, either via while-no-input or some other
mechanism.  Doing that for her in the library is violating the premise
of timer functions as one knows them.

> But I had the impression that the original problem under discussion was
> not just due to the difficulty of writing code that handles "random
> aborts", but rather due to the fact that `while-no-input` sometimes caused
> undesired random aborts even when the user didn't hit any key.
> This would be a bug in `while-no-input` which we should investigate
> a fix (it's likely due to some "innocuous" event being received which
> `while-no-input` mistakes for user-input; could be an event linked to
> some kind of notification service like dbus, file-notifications, ...).

Yes, there is that too.  While-no-input has all those Heisenbergian
effects to add to it.  But this was no heisenberg, I think.  I was
pressing C-n the whole time, so that's "input".

João