aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2023-01-07 10:06:03 +0100
committerbfredl <bjorn.linse@gmail.com>2023-01-09 11:17:11 +0100
commit1d16bba4d8b8b648d2dabd610924bcf3051a0f29 (patch)
tree9ea37b95a190d055e37deabb3c556edd83bded70
parentc19bd47c0a2e3cc77d7f5e41ed184edb41685bd3 (diff)
downloadrneovim-1d16bba4d8b8b648d2dabd610924bcf3051a0f29.tar.gz
rneovim-1d16bba4d8b8b648d2dabd610924bcf3051a0f29.tar.bz2
rneovim-1d16bba4d8b8b648d2dabd610924bcf3051a0f29.zip
fix(embed): handle stdio in server properly
Rename stdin/stdout in the server, so that RPC data won't get corrupted. This also restores the use of stderr to write directly to the terminal.
-rw-r--r--src/nvim/channel.c8
-rw-r--r--src/nvim/channel.h2
-rw-r--r--src/nvim/event/libuv_process.c3
-rw-r--r--src/nvim/event/process.c3
-rw-r--r--src/nvim/event/process.h5
-rw-r--r--src/nvim/main.c17
-rw-r--r--src/nvim/os/pty_process_unix.c8
-rw-r--r--src/nvim/ui_client.c5
8 files changed, 40 insertions, 11 deletions
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index f2e5a37b34..386ec832eb 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -377,6 +377,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader
} else {
has_out = rpc || callback_reader_set(chan->on_data);
has_err = callback_reader_set(chan->on_stderr);
+ proc->fwd_err = chan->on_stderr.fwd_err;
}
switch (stdin_mode) {
@@ -519,6 +520,13 @@ uint64_t channel_from_stdio(bool rpc, CallbackReader on_output, const char **err
stdout_dup_fd = os_dup(STDOUT_FILENO);
os_replace_stdout_and_stderr_to_conout();
}
+#else
+ if (embedded_mode) {
+ stdin_dup_fd = dup(STDIN_FILENO);
+ stdout_dup_fd = dup(STDOUT_FILENO);
+ dup2(STDERR_FILENO, STDOUT_FILENO);
+ dup2(STDERR_FILENO, STDIN_FILENO);
+ }
#endif
rstream_init_fd(&main_loop, &channel->stream.stdio.in, stdin_dup_fd, 0);
wstream_init_fd(&main_loop, &channel->stream.stdio.out, stdout_dup_fd, 0);
diff --git a/src/nvim/channel.h b/src/nvim/channel.h
index d7f32d8988..5743eaead5 100644
--- a/src/nvim/channel.h
+++ b/src/nvim/channel.h
@@ -66,6 +66,7 @@ typedef struct {
garray_T buffer;
bool eof;
bool buffered;
+ bool fwd_err;
const char *type;
} CallbackReader;
@@ -73,6 +74,7 @@ typedef struct {
.self = NULL, \
.buffer = GA_EMPTY_INIT_VALUE, \
.buffered = false, \
+ .fwd_err = false, \
.type = NULL })
static inline bool callback_reader_set(CallbackReader reader)
{
diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c
index 811d96ff93..10a09275d9 100644
--- a/src/nvim/event/libuv_process.c
+++ b/src/nvim/event/libuv_process.c
@@ -85,6 +85,9 @@ int libuv_process_spawn(LibuvProcess *uvproc)
uvproc->uvstdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
uvproc->uvstdio[2].data.stream = STRUCT_CAST(uv_stream_t,
&proc->err.uv.pipe);
+ } else if (proc->fwd_err) {
+ uvproc->uvstdio[2].flags = UV_INHERIT_FD;
+ uvproc->uvstdio[2].data.fd = STDERR_FILENO;
}
int status;
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index 2fa789ac9a..9dfd6f329a 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -43,6 +43,9 @@ static int exit_need_delay = 0;
int process_spawn(Process *proc, bool in, bool out, bool err)
FUNC_ATTR_NONNULL_ALL
{
+ // forwarding stderr contradicts with processing it internally
+ assert(!(err && proc->fwd_err));
+
if (in) {
uv_pipe_init(&proc->loop->uv, &proc->in.uv.pipe, 0);
} else {
diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h
index 26e03ff4f3..e0057faffb 100644
--- a/src/nvim/event/process.h
+++ b/src/nvim/event/process.h
@@ -38,7 +38,7 @@ struct process {
/// Exit handler. If set, user must call process_free().
process_exit_cb cb;
internal_process_cb internal_exit_cb, internal_close_cb;
- bool closed, detach, overlapped;
+ bool closed, detach, overlapped, fwd_err;
MultiQueue *events;
};
@@ -62,7 +62,8 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data)
.closed = false,
.internal_close_cb = NULL,
.internal_exit_cb = NULL,
- .detach = false
+ .detach = false,
+ .fwd_err = false,
};
}
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 9bb9eea4f6..953385836b 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -279,6 +279,15 @@ int main(int argc, char **argv)
// argument list "global_alist".
command_line_scan(&params);
+#ifndef MSWIN
+ int tty_fd = params.input_isatty
+ ? STDIN_FILENO
+ : (params.output_isatty
+ ? STDOUT_FILENO
+ : (params.err_isatty ? STDERR_FILENO : -1));
+ pty_process_save_termios(tty_fd);
+#endif
+
nlua_init(argv, argc, params.lua_arg0);
TIME_MSG("init lua interpreter");
@@ -1455,14 +1464,6 @@ static void check_and_set_isatty(mparm_T *paramp)
stdout_isatty
= paramp->output_isatty = os_isatty(STDOUT_FILENO);
paramp->err_isatty = os_isatty(STDERR_FILENO);
-#ifndef MSWIN
- int tty_fd = paramp->input_isatty
- ? STDIN_FILENO
- : (paramp->output_isatty
- ? STDOUT_FILENO
- : (paramp->err_isatty ? STDERR_FILENO : -1));
- pty_process_save_termios(tty_fd);
-#endif
TIME_MSG("window checked");
}
diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c
index 143f0b3900..cd2150a6a6 100644
--- a/src/nvim/os/pty_process_unix.c
+++ b/src/nvim/os/pty_process_unix.c
@@ -168,6 +168,14 @@ static struct termios termios_default;
/// @param tty_fd TTY file descriptor, or -1 if not in a terminal.
void pty_process_save_termios(int tty_fd)
{
+ if (embedded_mode) {
+ // TODO(bfredl): currently we cannot use the state of the host terminal in
+ // the server. when the TUI process launches the server, the state has already
+ // changed. we would need to serialize termios_default in the TUI process and
+ // transmit it. Altough, just always using the clean slate of init_termios() might
+ // be preferrable anyway.
+ return;
+ }
if (tty_fd == -1) {
return;
}
diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c
index 2821054909..ff82fd3239 100644
--- a/src/nvim/ui_client.c
+++ b/src/nvim/ui_client.c
@@ -41,8 +41,11 @@ uint64_t ui_client_start_server(int argc, char **argv)
}
args[args_idx++] = NULL;
+ CallbackReader on_err = CALLBACK_READER_INIT;
+ on_err.fwd_err = true;
+
Channel *channel = channel_job_start(args, CALLBACK_READER_INIT,
- CALLBACK_READER_INIT, CALLBACK_NONE,
+ on_err, CALLBACK_NONE,
false, true, true, false, kChannelStdinPipe,
NULL, 0, 0, NULL, &exit_status);
if (ui_client_forward_stdin) {