diff options
-rw-r--r-- | src/nvim/globals.h | 3 | ||||
-rw-r--r-- | src/nvim/if_cscope.c | 1 | ||||
-rw-r--r-- | src/nvim/main.c | 16 | ||||
-rw-r--r-- | src/nvim/misc1.c | 1 | ||||
-rw-r--r-- | src/nvim/os/input.c | 6 | ||||
-rw-r--r-- | src/nvim/os/os.h | 1 | ||||
-rw-r--r-- | src/nvim/os/rstream.c | 5 | ||||
-rw-r--r-- | src/nvim/os/stream.c | 26 |
8 files changed, 50 insertions, 9 deletions
diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 1d93900a94..f012358404 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -1217,6 +1217,9 @@ EXTERN char *ignoredp; // If a msgpack-rpc channel should be started over stdin/stdout EXTERN bool embedded_mode INIT(= false); +/// TTY from which input was gathered. +EXTERN int global_input_fd INIT(= 0); + /// Used to track the status of external functions. /// Currently only used for iconv(). typedef enum { diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index 407709866c..b3d61038c3 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -820,6 +820,7 @@ err_closing: if (execl("/bin/sh", "sh", "-c", cmd, (char *)NULL) == -1) PERROR(_("cs_create_connection exec failed")); + stream_set_blocking(global_input_fd, true); //normalize stream (#2598) exit(127); /* NOTREACHED */ default: /* parent. */ diff --git a/src/nvim/main.c b/src/nvim/main.c index 5f0372f30e..6ae96a7c69 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -271,17 +271,15 @@ int main(int argc, char **argv) || params.output_isatty || params.err_isatty); if (reading_input) { - // Its possible that one of the startup commands(arguments, sourced scripts - // or plugins) will prompt the user, so start reading from a tty stream - // now. - int fd = fileno(stdin); + // One of the startup commands (arguments, sourced scripts or plugins) may + // prompt the user, so start reading from a tty now. + global_input_fd = fileno(stdin); if (!params.input_isatty || params.edit_type == EDIT_STDIN) { - // use stderr or stdout since stdin is not a tty and/or could be used to - // read the file we'll edit when the "-" argument is given(eg: cat file | - // nvim -) - fd = params.err_isatty ? fileno(stderr) : fileno(stdout); + // Use stderr or stdout since stdin is not a tty and/or could be used to + // read the "-" file (eg: cat file | nvim -) + global_input_fd = params.err_isatty ? fileno(stderr) : fileno(stdout); } - input_start_stdin(fd); + input_start_stdin(global_input_fd); } // open terminals when opening files that start with term:// diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 3ae3d6e30e..13e5f273e0 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -2699,6 +2699,7 @@ void preserve_exit(void) } ml_close_all(false); // close all memfiles, without deleting + stream_set_blocking(global_input_fd, true); //normalize stream (#2598) mch_errmsg("Vim: Finished.\n"); diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 486171b48a..5dcaee8304 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -8,6 +8,7 @@ #include "nvim/api/private/defs.h" #include "nvim/os/input.h" #include "nvim/os/event.h" +#include "nvim/os/os.h" #include "nvim/os/rstream_defs.h" #include "nvim/os/rstream.h" #include "nvim/ascii.h" @@ -61,9 +62,14 @@ void input_start_stdin(int fd) void input_stop_stdin(void) { if (!read_stream) { + // In some cases (i.e. "nvim && read") where we do not explicitly play with + // std{in,out,err}, some other module/library nevertheless sets the stream + // to non-blocking; we still must "fix" the stream (#2598) in those cases. + stream_set_blocking(global_input_fd, true); // normalize stream (#2598) return; } + rstream_set_blocking(read_stream, true); // normalize stream (#2598) rstream_stop(read_stream); rstream_free(read_stream); read_stream = NULL; diff --git a/src/nvim/os/os.h b/src/nvim/os/os.h index 69bd1ff4fd..3dd099890c 100644 --- a/src/nvim/os/os.h +++ b/src/nvim/os/os.h @@ -12,6 +12,7 @@ # include "os/mem.h.generated.h" # include "os/env.h.generated.h" # include "os/users.h.generated.h" +# include "os/stream.h.generated.h" #endif #endif // NVIM_OS_OS_H diff --git a/src/nvim/os/rstream.c b/src/nvim/os/rstream.c index 702f282d53..55bf89d768 100644 --- a/src/nvim/os/rstream.c +++ b/src/nvim/os/rstream.c @@ -297,6 +297,11 @@ void rstream_stop(RStream *rstream) } } +int rstream_set_blocking(RStream *rstream, bool blocking) +{ + return uv_stream_set_blocking(rstream->stream, blocking); +} + /// Returns the number of bytes ready for consumption in `rstream` size_t rstream_pending(RStream *rstream) { diff --git a/src/nvim/os/stream.c b/src/nvim/os/stream.c new file mode 100644 index 0000000000..35cb41081d --- /dev/null +++ b/src/nvim/os/stream.c @@ -0,0 +1,26 @@ +// Functions for working with stdio streams (as opposed to RStream/WStream). + +#include <stdio.h> +#include <stdbool.h> + +#include <uv.h> + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "os/stream.c.generated.h" +#endif + +/// Sets the stream associated with `fd` to "blocking" mode. +/// +/// @return `0` on success, or `-errno` on failure. +int stream_set_blocking(int fd, bool blocking) +{ + int flags = fcntl(fd, F_GETFL, 0); + int err = 0; + if (!blocking && !(flags & O_NONBLOCK)) { + err = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + } else if (blocking && (flags & O_NONBLOCK)) { + err = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + } + return err == -1 ? -errno : 0; +} + |