Subject: bug#17139: Race condition in complete-in-region: should we be using pre-command-hook, not post-command-hook?

From: Daniel Colascione <[email-masked]>
Date: Sun, 30 Mar 2014 14:49:59 -0700

On 03/30/2014 02:39 PM, Stefan Monnier wrote:
>>> run post-command-hook; completion-in-region--postch is on the list of
>>> hooks to run.  This function runs completion-in-region-mode--predicate,
>>> which makes a hidden call to the subprocess;
> 
> Using the subprocess from completion-in-region--postch sounds
> like a problem/bug, indeed.  Why do we(I?) do that?
> 
>>> Why can't we do the completion-in-region--postch stuff in pre-command-hook?
> 
> Because pre-command-hook would come even later (it would only disable
> completion-in-region-mode at the beginning of the next command after RET).

You're right: that's a bad solution.  I was thinking we could somehow
detect RET and other side-effect-ful commands, but just augmenting
comint-send-input is better.
> 
>> +  ;; If we're currently completing, stop.  We're definitely done
>> +  ;; completing, and by sending the input, we might cause side effects
>> +  ;; that will confuse the code running in the completion
>> +  ;; post-command-hook.
>> +  (when completion-in-region-mode
>> +    (completion-in-region-mode -1))
> 
> I see you installed it, thanks, I think it's OK.  But I'd also like to
> know why we contact the subprocess from completion-in-region--postch,
> because that's risky.

In my case, I have a JavaScript repl to which Emacs connects over a
socket. Each connection gets a separate JavaScript global environment,
so completion in the comint buffer has to use the same underlying socket
that's connected to the buffer. Completion works by using comint
redirection to send JavaScript over the socket, then waiting for a
reply. completion-in-region--postch needs to use the normal completion
machinery (via the predicate set up in completion-at-point) to detect
whether the completion region has changed, and this machinery contacts
the subprocess to find the completion candidates.

Come to think of it, supplying a function instead of a simple list of
strings as the completion table returned from the completion function
would probably help too, since then completion-in-region--postch could
inspect the first element of the returned list (the completion region
start) without having to actually "force the promise" and resolve the
whole list after every command.