[vim/vim] proposal: some way to interrupt channel-backed command/function (#4224)

52 views
Skip to first unread message

Paul Jolly

unread,
Apr 8, 2019, 7:49:47 AM4/8/19
to vim/vim, Subscribed

Is your feature request related something that is currently hard to do? Please describe.

At present it is is possible to interrupt the current (search) command using <C-c> (see :help CTRL-C)

However, this does not appear to translate to a world of channels.

A channel-backed plugin, just like a regular plugin, can get "stuck" running external commands (or the equivalent thereof). So <C-c> ends up being an important "kill" command.

Describe the solution you'd like

Some means by which <C-c> can be used in a channel world to interrupt a ch_evalexpr call.

Describe alternatives you've considered

I can't honestly think of a workaround/alternative here 😄

Additional context

This question is raised in the context of https://github.com/myitcv/govim

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.

Bram Moolenaar

unread,
Apr 8, 2019, 10:15:27 AM4/8/19
to vim/vim, Subscribed

Can you please provide a working example?
You probably don't want to disconnect all channels on a CTRL-C. So what would be OK to cancel?

Paul Jolly

unread,
Apr 8, 2019, 10:36:28 AM4/8/19
to vim/vim, Subscribed

Can you please provide a working example?

I can probably provide a simulation of a situation that goes "wrong" in this way if that's useful? Would simply be a long sleep that gets triggered as a result of, say, an autocmd on BufWritePre or a regular command call.

My current use case is as follows. Note, it is an exceptional use case, i.e. the user does not want to find themselves in this position, and the tool in question shouldn't really misbehave like this and take so long that the user considers hitting <C-c>

In https://github.com/myitcv/govim we have a BufWritePre autocmd that, via the gopls LSP, effectively runs a tool that checks the buffer/file in question, adds an missing imports, formats the resulting code and returns the results (to Vim to then write).

The problem is that in certain cases, this tool can end up running an extremely expensive query as it tries to determine missing imports.

Now it's absolutely correct to point out the tool should not behave like, but there are plenty of edge cases that lead to pathological behaviour. And it's not necessarily just this tool, could be lack-of-network related etc. Feels like there are a number of cases that might fall under this umbrella.

You probably don't want to disconnect all channels on a CTRL-C

Agreed.

So what would be OK to cancel?

The following guess is based on pure guesswork of what currently happens, so please take it with that pinch of salt.

Let's assume I currently have an autocmd that is "hooked" to run a command-line version of exactly the same tool, but does so via system(). If it ends up taking too long, I can hit <C-c> and I'm guessing a signal is sent to said process.

Would it be possible to achieve much the same with a channel-based setup? At least the way I've implemented https://github.com/vim/vim, if I am in the process of handling a function/command/autocmd callback I am not blocking the read loop, so could happily process a special ch_sendexpr call that included some sort of signal.

But then these are just random thoughts based on zero real understanding of the Vim side of things.

Please let me know if there's anything else I can help answer however.

Paul Jolly

unread,
Aug 26, 2019, 10:04:17 AM8/26/19
to vim/vim, Subscribed

Ran into a few more instances of this recently whilst trying to debug problems within govim.

The only additional detail to add is that any implementation would of course require the remote plugin to also handle the cancel call, which may have recursively made a call back to Vim etc. It gets complicated quickly.

Paul Jolly

unread,
Jan 19, 2020, 11:43:56 AM1/19/20
to vim/vim, Subscribed

Hi Bram - any thoughts on whether there's something we can do here?

—
You are receiving this because you are subscribed to this thread.

Reply to this email directly, view it on GitHub, or unsubscribe.

Bram Moolenaar

unread,
Jan 19, 2020, 3:36:03 PM1/19/20
to vim/vim, Subscribed

In this situation, is Vim still responding to commands? Or is it actually hanging in a channel request?

—
You are receiving this because you are subscribed to this thread.

Reply to this email directly, view it on GitHub, or unsubscribe.

Paul Jolly

unread,
Jan 20, 2020, 5:57:06 AM1/20/20
to vim/vim, Subscribed

In this situation it is blocked: the user invoked a command that is blocked on a ch_evalexpr.

—
You are receiving this because you are subscribed to this thread.

Reply to this email directly, view it on GitHub, or unsubscribe.

Bram Moolenaar

unread,
Jan 20, 2020, 6:16:07 AM1/20/20
to vim/vim, Subscribed

> In this situation it is blocked: the user invoked a command that is
> blocked on a `ch_evalexpr`.

OK, then the Ctrl-C can mean "interrupt what is going on right now".
Does that mean to give up on this request, or close the channel?
In case of an expensive query you would want the first, if it's going to
try another request next it would be the second. Hard to predict.
Perhaps have a setting on the channel? "kill after N interrupts", which
would be one to kill the channel always.


--
Looking at Perl through Lisp glasses, Perl looks atrocious.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

—
You are receiving this because you are subscribed to this thread.

Reply to this email directly, view it on GitHub, or unsubscribe.

Paul Jolly

unread,
Jan 20, 2020, 6:25:47 AM1/20/20
to vim/vim, Subscribed

then the Ctrl-C can mean "interrupt what is going on right now"

Yes, where "going on right now" is from the user's perspective. Because even in this state Vim is still responsive to govim sending it messages. i.e. we only want to cancel the ch_evalexpr that resulted from the command (which in this case was :w)

Does that mean to give up on this request

I think so, yes. Because my hope is that we will be able to tidy up sufficiently on the govim side to not require a restart.

or close the channel

I don't think we need this. Because that means restarting govim, and that might well not be necessary.

We might still want to have a GOVIMRestart command which does close the channel, tidy up and restart... but I think that's somewhat orthogonal to what we need in this case.

Either way we will have to make sure we tidy up state etc after the cancel, just in case certain events didn't get handled etc. This is, perhaps, an argument somewhat more in favour of closing the channel and starting from scratch now that I come to think about it.

Does interrupting the request feel like a good starting point for you?

—
You are receiving this because you are subscribed to this thread.

Reply to this email directly, view it on GitHub, or unsubscribe.

Bram Moolenaar

unread,
Jan 20, 2020, 12:22:18 PM1/20/20
to vim/vim, Subscribed

> > then the Ctrl-C can mean "interrupt what is going on right now"
>
> Yes, where "going on right now" is from the user's perspective.
> Because even in this state Vim is still responsive to `govim` sending
> it messages. i.e. we only want to cancel the `ch_evalexpr` that
> resulted from the command (which in this case was `:w`)

>
> > Does that mean to give up on this request
>
> I think so, yes. Because my hope is that we will be able to tidy up
> sufficiently on the `govim` side to not require a restart.
>
> > or close the channel
>
> I don't think we need this. Because that means restarting `govim`, and

> that might well not be necessary.
>
> We might still want to have a `GOVIMRestart` command which does close
> the channel, tidy up and restart... but I think that's somewhat
> orthogonal to what we need in this case.
>
> Either way we will have to make sure we tidy up state etc after the
> cancel, just in case certain events didn't get handled etc. This is,
> perhaps, an argument somewhat more in favour of closing the channel
> and starting from scratch now that I come to think about it.
>
> Does interrupting the request feel like a good starting point for you?

Interrupting the blocking wait sounds doable. But the implementation
isn't that simple. I guess the wait happens in channel_wait(), which
uses select() to wait for something to read or write. Handling keyboard
here would not work. So we might have to break up the timeout in 100
msec parts, then check for CTRL-C typed, then back to waiting.

This has to be implemented three times (Windows, select() and polling).
Any volunteers?

--
Friends? I have lots of friends! In fact, I have all episodes ever made.


/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

—


You are receiving this because you are subscribed to this thread.

Reply to this email directly, view it on GitHub, or unsubscribe.

Tom M

unread,
Jan 21, 2020, 8:04:43 AM1/21/20
to vim...@googlegroups.com
I am not sure how portable it would be but can't the signal handler be
configured in such a way that it lets the select() fail with EINTR after it
catches the SIGINT for CTRL-C?

That way it wouldn't be necessary to break the waiting each 100 msec to check
for CTRL-C and loop if none has come.

Tom

Bram Moolenaar

unread,
Jan 21, 2020, 12:40:10 PM1/21/20
to vim...@googlegroups.com, Tom M
Vim works in raw mode where CTRL-C does not cause a SIGINT. Vim needs
to read the input to check for typed characters. That is done by
calling ui_breakcheck().

--
BLACK KNIGHT: I'm invincible!
ARTHUR: You're a looney.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
Reply all
Reply to author
Forward
0 new messages