-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(job): add parameter to close stdin #14812
Conversation
@gpanders Out of curiosity, have you confirmed that closing stdin here would cause ripgrep to do the right thing? |
I have and it does. |
should we call it |
Sure, I like that. What do you want to call the current/default behavior? I'm thinking either |
@bfredl I changed |
sure, if the name choices picked by vim8 is reasonable, we could just as well reuse them :) |
The CI checks seem to be failing for something unrelated to this PR |
Some programs behave differently when they detect that stdin is being piped. This can be problematic when these programs are used with the job control API where stdin is attached, but not typically used. It is possible to run the job using a PTY which circumvents this problem, but that includes a lot of overhead when simply closing the stdin pipe would suffice. To enable this behavior, add a new parameter to the jobstart options dict called "stdin" with two valid values: "pipe" (the default) implements the existing behavior of opening a channel for stdin and "null" which disconnects stdin (or, if you prefer, connects it to /dev/null). This is extensible so that other modes can be added in the future.
stdin is a macro in Windows builds.
A simple test would be good. doesn't need to be complicated, could just be |
I modified the |
Starting with version 13, ripgrep always stats stdin and if it's not a TTY it uses it to read data. Unfortunately, Neovim always attaches a pipe to stdin by default and that leads to ripgrep reading nothing and it essentially breaks vim-grepper when targeting a recent version of ripgrep. (see neovim/neovim#14812 for more info) This was fixed in nvim by adding an option to jobstart to not pipe stdin (see neovim/neovim#14812). So we use this here which I verified fixes search through rg. Note that I'm not 100% sure how to gate this. It was technically added as a commit to neovim after 0.5 shipped so I imagine it will technically be released in 0.5.1. But it should also be harmless to only gate this to `nvim` since the options are a dictionary and old versions of neovim will just ignore that `stdin` key.
Starting with version 13, ripgrep always stats stdin and if it's not a TTY it uses it to read data. Unfortunately, Neovim always attaches a pipe to stdin by default and that leads to ripgrep reading nothing and it essentially breaks vim-grepper when targeting a recent version of ripgrep. (see neovim/neovim#14812 for more info) This was fixed in nvim by adding an option to jobstart to not pipe stdin (see neovim/neovim#14812). So we use this here which I verified fixes search through rg. Note that I'm not 100% sure how to gate this. It was technically added as a commit to neovim after 0.5 shipped so I imagine it will technically be released in 0.5.1. But it should also be harmless to only gate this to `nvim` since the options are a dictionary and old versions of neovim will just ignore that `stdin` key.
typedef enum { | ||
kChannelStdinPipe, | ||
kChannelStdinNull, | ||
} ChannelStdinMode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it make sense to name this ChannelMode, and add kChannelBuffered, then use this internally to model the stderr_buffered/stdout_buffered flags? And potentially we would add stderr
, stdout
string options to jobstart(), and deprecate the stderr_buffered/stdout_buffered booleans.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if that would make sense, as that introduces more edge cases we'd need to check for.
For example, what happens when "stdout"
is set to "null"
but an "on_stdout"
callback is provided? What does it mean when "stdin"
is set to "buffered"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, what happens when
"stdout"
is set to"null"
but an"on_stdout"
callback is provided? What does it mean when"stdin"
is set to"buffered"
?
At the input layer we would of course validate valid values, just as "foo" is not a valid value for the stdin
mode parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that, but the point I was trying to make was that I don't know if the additional validation required results in a net reduction in complexity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would only make sense if we actually add more flags to the jobstart() interface (e.g stdout="file").
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we could put most of the validation responsibility on the user. We just return an error if "stdout"
is anything other than "null"
and "on_stdout"
is missing and vice versa.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this makes sense for the existing feature set, but perhaps it does in a PR adding "buffer" and "file" modes (so there actually are shared modes between instreams and outsteams).
Some programs behave differently when they detect that stdin is being
piped. This can be problematic when these programs are used with the job
control API where stdin is attached, but not typically used. It is
possible to run the job using a PTY which circumvents this problem, but
that includes a lot of overhead when simply closing the stdin pipe would
suffice.
To enable this behavior, add a new parameter to the jobstart options
dict called "stdin" with two valid values: "pipe" (the default)
implements the existing behavior of opening a channel for stdin and
"null" which disconnects stdin (or, if you prefer, connects it to
/dev/null). This is extensible so that other modes can be added in the
future.
Context
This was inspired by a recent change in ripgrep where the behavior of ripgrep changes if it detects that
stdin
is open. In the linked issue, the ripgrep maintainer rightfully asks the question, "Why is it attaching a socket to stdin in the first place?" (see also vim/vim#4529).By default Neovim always attaches
stdin
and only attachesstdout
andstderr
if the appropriate callbacks are specified. Presently, the only way to disable automatically opening a stdin channel is to run the command in a pty using the'pty'
option; however, this adds a lot of overhead to simply avoid opening a stdin channel. This PR modifies that functionality by allowing thestdin
channel to be closed (or rather, never be opened) if the"stdin"
option is set to"null"
in the options dict passed tojobstart
.