aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os/shell.c
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2016-10-18 14:39:08 +0200
committerJustin M. Keyes <justinkz@gmail.com>2016-10-19 01:39:05 +0200
commit9706664b8827614817a43f3a4ac4b6ae8463a906 (patch)
tree9c0288adb64b6779b6e19dfc873f1ba0fe65b16f /src/nvim/os/shell.c
parent16da3a6fe01de74eaebfd4750dabe27b3b7ab068 (diff)
downloadrneovim-9706664b8827614817a43f3a4ac4b6ae8463a906.tar.gz
rneovim-9706664b8827614817a43f3a4ac4b6ae8463a906.tar.bz2
rneovim-9706664b8827614817a43f3a4ac4b6ae8463a906.zip
system('foo &', 'bar'): Show error, don't crash.
Closes #3529 Closes #5241 In Vim, :echo system('cat - &', 'foo') works because for both system() and :! Vim writes input to a temp file and uses shell syntax to redirect the file to the backgrounded `cat` (get_cmd_output() .. make_filter_cmd()). In Nvim, :echo system('cat - &', 'foo') fails because we write the input directly via pipes (shell.c:do_os_system()), but (per POSIX[1]) backgrounded process input stream is redirected from /dev/null (unless overridden by shell redirection; supported only by some shells [2]), so our writes are ignored, the process exits quickly, and if we are writing data larger than the buffer size we'll see EPIPE. This still works: :%w !tee > foo1358.txt & but this does not: :%w !tee foo1358.txt & though it *should* (why doesn't it?) because we still do the temp file dance in do_bang() .. do_filter(). [1] http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_03_02 [2] http://unix.stackexchange.com/a/71218
Diffstat (limited to 'src/nvim/os/shell.c')
-rw-r--r--src/nvim/os/shell.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index e9a3dcbff8..18ee008d66 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -545,6 +545,16 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer,
static void shell_write_cb(Stream *stream, void *data, int status)
{
+ if (status) {
+ // Can happen if system() tries to send input to a shell command that was
+ // backgrounded (:call system("cat - &", "foo")). #3529 #5241
+ EMSG2(_("E5677: Error writing input to shell-command: %s"),
+ uv_err_name(status));
+ }
+ if (stream->closed) { // Process may have exited before this write.
+ ELOG("stream was already closed");
+ return;
+ }
stream_close(stream, NULL, NULL);
}