aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/event
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:23:01 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:23:01 +0000
commit142d9041391780ac15b89886a54015fdc5c73995 (patch)
tree0f6b5cac1a60810a03f52826c9e67c9e2780b033 /src/nvim/event
parentad86b5db74922285699ab2a1dbb2ff20e6268a33 (diff)
parent3c48d3c83fc21dbc0841f9210f04bdb073d73cd1 (diff)
downloadrneovim-142d9041391780ac15b89886a54015fdc5c73995.tar.gz
rneovim-142d9041391780ac15b89886a54015fdc5c73995.tar.bz2
rneovim-142d9041391780ac15b89886a54015fdc5c73995.zip
Merge remote-tracking branch 'upstream/master' into userreg
Diffstat (limited to 'src/nvim/event')
-rw-r--r--src/nvim/event/libuv_process.c17
-rw-r--r--src/nvim/event/libuv_process.h3
-rw-r--r--src/nvim/event/loop.c11
-rw-r--r--src/nvim/event/loop.h4
-rw-r--r--src/nvim/event/multiqueue.c6
-rw-r--r--src/nvim/event/process.c44
-rw-r--r--src/nvim/event/process.h14
-rw-r--r--src/nvim/event/rstream.c9
-rw-r--r--src/nvim/event/signal.c1
-rw-r--r--src/nvim/event/signal.h3
-rw-r--r--src/nvim/event/socket.c11
-rw-r--r--src/nvim/event/socket.h3
-rw-r--r--src/nvim/event/stream.c4
-rw-r--r--src/nvim/event/stream.h6
-rw-r--r--src/nvim/event/time.h4
-rw-r--r--src/nvim/event/wstream.c6
-rw-r--r--src/nvim/event/wstream.h3
17 files changed, 117 insertions, 32 deletions
diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c
index f012bacdd9..e528d21a71 100644
--- a/src/nvim/event/libuv_process.c
+++ b/src/nvim/event/libuv_process.c
@@ -2,16 +2,18 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <assert.h>
+#include <stdint.h>
#include <uv.h>
+#include "nvim/eval/typval.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/loop.h"
#include "nvim/event/process.h"
-#include "nvim/event/rstream.h"
-#include "nvim/event/wstream.h"
+#include "nvim/event/stream.h"
#include "nvim/log.h"
#include "nvim/macros.h"
#include "nvim/os/os.h"
+#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/libuv_process.c.generated.h"
@@ -40,11 +42,19 @@ int libuv_process_spawn(LibuvProcess *uvproc)
#endif
uvproc->uvopts.exit_cb = exit_cb;
uvproc->uvopts.cwd = proc->cwd;
+
uvproc->uvopts.stdio = uvproc->uvstdio;
uvproc->uvopts.stdio_count = 3;
uvproc->uvstdio[0].flags = UV_IGNORE;
uvproc->uvstdio[1].flags = UV_IGNORE;
uvproc->uvstdio[2].flags = UV_IGNORE;
+
+ if (ui_client_forward_stdin) {
+ assert(UI_CLIENT_STDIN_FD == 3);
+ uvproc->uvopts.stdio_count = 4;
+ uvproc->uvstdio[3].data.fd = 0;
+ uvproc->uvstdio[3].flags = UV_INHERIT_FD;
+ }
uvproc->uv.data = proc;
if (proc->env) {
@@ -77,6 +87,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/libuv_process.h b/src/nvim/event/libuv_process.h
index 1132ce79ca..4472839944 100644
--- a/src/nvim/event/libuv_process.h
+++ b/src/nvim/event/libuv_process.h
@@ -3,13 +3,14 @@
#include <uv.h>
+#include "nvim/event/loop.h"
#include "nvim/event/process.h"
typedef struct libuv_process {
Process process;
uv_process_t uv;
uv_process_options_t uvopts;
- uv_stdio_container_t uvstdio[3];
+ uv_stdio_container_t uvstdio[4];
} LibuvProcess;
static inline LibuvProcess libuv_process_init(Loop *loop, void *data)
diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c
index 3329cbd574..ab2524c1a9 100644
--- a/src/nvim/event/loop.c
+++ b/src/nvim/event/loop.c
@@ -1,13 +1,16 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-#include <stdarg.h>
+#include <stdbool.h>
#include <stdint.h>
+#include <stdlib.h>
#include <uv.h>
+#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
-#include "nvim/event/process.h"
#include "nvim/log.h"
+#include "nvim/memory.h"
+#include "nvim/os/time.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/loop.c.generated.h"
@@ -40,7 +43,7 @@ void loop_init(Loop *loop, void *data)
/// @param once true: process at most one `Loop.uv` event.
/// false: process until `ms` timeout (only has effect if `ms` > 0).
/// @return true if `ms` > 0 and was reached
-bool loop_uv_run(Loop *loop, int ms, bool once)
+bool loop_uv_run(Loop *loop, int64_t ms, bool once)
{
if (loop->recursive++) {
abort(); // Should not re-enter uv_run
@@ -79,7 +82,7 @@ bool loop_uv_run(Loop *loop, int ms, bool once)
/// > 0: timeout after `ms`.
/// < 0: wait forever.
/// @return true if `ms` > 0 and was reached
-bool loop_poll_events(Loop *loop, int ms)
+bool loop_poll_events(Loop *loop, int64_t ms)
{
bool timeout_expired = loop_uv_run(loop, ms, true);
multiqueue_process_events(loop->fast_events);
diff --git a/src/nvim/event/loop.h b/src/nvim/event/loop.h
index c0bcda40ce..b2265a726d 100644
--- a/src/nvim/event/loop.h
+++ b/src/nvim/event/loop.h
@@ -58,7 +58,7 @@ typedef struct loop {
// Poll for events until a condition or timeout
#define LOOP_PROCESS_EVENTS_UNTIL(loop, multiqueue, timeout, condition) \
do { \
- int remaining = timeout; \
+ int64_t remaining = timeout; \
uint64_t before = (remaining > 0) ? os_hrtime() : 0; \
while (!(condition)) { \
LOOP_PROCESS_EVENTS(loop, multiqueue, remaining); \
@@ -66,7 +66,7 @@ typedef struct loop {
break; \
} else if (remaining > 0) { \
uint64_t now = os_hrtime(); \
- remaining -= (int)((now - before) / 1000000); \
+ remaining -= (int64_t)((now - before) / 1000000); \
before = now; \
if (remaining <= 0) { \
break; \
diff --git a/src/nvim/event/multiqueue.c b/src/nvim/event/multiqueue.c
index 40d20033e0..e05084b656 100644
--- a/src/nvim/event/multiqueue.c
+++ b/src/nvim/event/multiqueue.c
@@ -46,14 +46,14 @@
// other sources and focus on a specific channel.
#include <assert.h>
-#include <stdarg.h>
#include <stdbool.h>
-#include <stdint.h>
+#include <stddef.h>
#include <uv.h>
+#include "nvim/event/defs.h"
#include "nvim/event/multiqueue.h"
+#include "nvim/lib/queue.h"
#include "nvim/memory.h"
-#include "nvim/os/time.h"
typedef struct multiqueue_item MultiQueueItem;
struct multiqueue_item {
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index e029f778f6..1a524a56ca 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -2,20 +2,25 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <assert.h>
+#include <inttypes.h>
+#include <signal.h>
#include <stdlib.h>
#include <uv.h>
+#include "klib/klist.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/loop.h"
#include "nvim/event/process.h"
-#include "nvim/event/rstream.h"
-#include "nvim/event/wstream.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/macros.h"
+#include "nvim/main.h"
#include "nvim/os/process.h"
#include "nvim/os/pty_process.h"
#include "nvim/os/shell.h"
+#include "nvim/os/time.h"
+#include "nvim/rbuffer.h"
+#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/process.c.generated.h"
@@ -32,10 +37,16 @@ void __gcov_flush(void);
static bool process_is_tearing_down = false;
+// Delay exit until handles are closed, to avoid deadlocks
+static int exit_need_delay = 0;
+
/// @returns zero on success, or negative error code
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 {
@@ -395,12 +406,41 @@ static void process_close_handles(void **argv)
exit_need_delay--;
}
+static void exit_delay_cb(uv_timer_t *handle)
+{
+ uv_timer_stop(&main_loop.exit_delay_timer);
+ multiqueue_put(main_loop.fast_events, exit_event, 1, main_loop.exit_delay_timer.data);
+}
+
+static void exit_event(void **argv)
+{
+ int status = (int)(intptr_t)argv[0];
+ if (exit_need_delay) {
+ main_loop.exit_delay_timer.data = argv[0];
+ uv_timer_start(&main_loop.exit_delay_timer, exit_delay_cb, 0, 0);
+ return;
+ }
+
+ if (!exiting) {
+ os_exit(status);
+ }
+}
+
+void exit_from_channel(int status)
+{
+ multiqueue_put(main_loop.fast_events, exit_event, 1, status);
+}
+
static void on_process_exit(Process *proc)
{
Loop *loop = proc->loop;
ILOG("exited: pid=%d status=%d stoptime=%" PRIu64, proc->pid, proc->status,
proc->stopped_time);
+ if (ui_client_channel_id) {
+ exit_from_channel(proc->status);
+ }
+
// Process has terminated, but there could still be data to be read from the
// OS. We are still in the libuv loop, so we cannot call code that polls for
// more data directly. Instead delay the reading after the libuv loop by
diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h
index 30254bfe07..e0057faffb 100644
--- a/src/nvim/event/process.h
+++ b/src/nvim/event/process.h
@@ -1,11 +1,20 @@
#ifndef NVIM_EVENT_PROCESS_H
#define NVIM_EVENT_PROCESS_H
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/event/rstream.h"
+#include "nvim/event/stream.h"
#include "nvim/event/wstream.h"
+struct process;
+
typedef enum {
kProcessTypeUv,
kProcessTypePty,
@@ -29,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;
};
@@ -53,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/event/rstream.c b/src/nvim/event/rstream.c
index 2847788ef8..a88d62fd6b 100644
--- a/src/nvim/event/rstream.c
+++ b/src/nvim/event/rstream.c
@@ -3,17 +3,18 @@
#include <assert.h>
#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
-#include <stdlib.h>
#include <uv.h>
-#include "nvim/ascii.h"
#include "nvim/event/loop.h"
#include "nvim/event/rstream.h"
+#include "nvim/event/stream.h"
#include "nvim/log.h"
+#include "nvim/macros.h"
#include "nvim/main.h"
-#include "nvim/memory.h"
-#include "nvim/vim.h"
+#include "nvim/os/os_defs.h"
+#include "nvim/rbuffer.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/rstream.c.generated.h"
diff --git a/src/nvim/event/signal.c b/src/nvim/event/signal.c
index 4a45a2ec2f..8256ca2091 100644
--- a/src/nvim/event/signal.c
+++ b/src/nvim/event/signal.c
@@ -1,6 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+#include <stddef.h>
#include <uv.h>
#include "nvim/event/loop.h"
diff --git a/src/nvim/event/signal.h b/src/nvim/event/signal.h
index 7fe352edef..f9adf62c20 100644
--- a/src/nvim/event/signal.h
+++ b/src/nvim/event/signal.h
@@ -4,6 +4,9 @@
#include <uv.h>
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
+
+struct signal_watcher;
typedef struct signal_watcher SignalWatcher;
typedef void (*signal_cb)(SignalWatcher *watcher, int signum, void *data);
diff --git a/src/nvim/event/socket.c b/src/nvim/event/socket.c
index 9ca3dcc276..10756015ad 100644
--- a/src/nvim/event/socket.c
+++ b/src/nvim/event/socket.c
@@ -2,23 +2,24 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <assert.h>
-#include <stdint.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
#include <uv.h>
#include "nvim/ascii.h"
#include "nvim/charset.h"
#include "nvim/event/loop.h"
-#include "nvim/event/rstream.h"
#include "nvim/event/socket.h"
-#include "nvim/event/wstream.h"
+#include "nvim/event/stream.h"
+#include "nvim/gettext.h"
#include "nvim/log.h"
#include "nvim/macros.h"
#include "nvim/main.h"
#include "nvim/memory.h"
#include "nvim/os/os.h"
#include "nvim/path.h"
-#include "nvim/strings.h"
-#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/socket.c.generated.h"
diff --git a/src/nvim/event/socket.h b/src/nvim/event/socket.h
index d30ae45502..c6fcdec4bb 100644
--- a/src/nvim/event/socket.h
+++ b/src/nvim/event/socket.h
@@ -4,9 +4,12 @@
#include <uv.h>
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/event/rstream.h"
#include "nvim/event/wstream.h"
+struct socket_watcher;
+
#define ADDRESS_MAX_SIZE 256
typedef struct socket_watcher SocketWatcher;
diff --git a/src/nvim/event/stream.c b/src/nvim/event/stream.c
index bfb7a551b9..0a4918636a 100644
--- a/src/nvim/event/stream.c
+++ b/src/nvim/event/stream.c
@@ -3,9 +3,11 @@
#include <assert.h>
#include <stdbool.h>
-#include <stdio.h>
+#include <stddef.h>
#include <uv.h>
+#include <uv/version.h>
+#include "nvim/event/loop.h"
#include "nvim/event/stream.h"
#include "nvim/log.h"
#include "nvim/macros.h"
diff --git a/src/nvim/event/stream.h b/src/nvim/event/stream.h
index b580d3c33d..33d2d6e775 100644
--- a/src/nvim/event/stream.h
+++ b/src/nvim/event/stream.h
@@ -6,8 +6,11 @@
#include <uv.h>
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/rbuffer.h"
+struct stream;
+
typedef struct stream Stream;
/// Type of function called when the Stream buffer is filled with data
///
@@ -16,8 +19,7 @@ typedef struct stream Stream;
/// @param count Number of bytes that was read.
/// @param data User-defined data
/// @param eof If the stream reached EOF.
-typedef void (*stream_read_cb)(Stream *stream, RBuffer *buf, size_t count,
- void *data, bool eof);
+typedef void (*stream_read_cb)(Stream *stream, RBuffer *buf, size_t count, void *data, bool eof);
/// Type of function called when the Stream has information about a write
/// request.
diff --git a/src/nvim/event/time.h b/src/nvim/event/time.h
index a6de89ad6e..e84488fdd6 100644
--- a/src/nvim/event/time.h
+++ b/src/nvim/event/time.h
@@ -1,9 +1,13 @@
#ifndef NVIM_EVENT_TIME_H
#define NVIM_EVENT_TIME_H
+#include <stdbool.h>
#include <uv.h>
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
+
+struct time_watcher;
typedef struct time_watcher TimeWatcher;
typedef void (*time_cb)(TimeWatcher *watcher, void *data);
diff --git a/src/nvim/event/wstream.c b/src/nvim/event/wstream.c
index d81ffa5c15..65391ba5cf 100644
--- a/src/nvim/event/wstream.c
+++ b/src/nvim/event/wstream.c
@@ -3,15 +3,13 @@
#include <assert.h>
#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
#include <uv.h>
#include "nvim/event/loop.h"
+#include "nvim/event/stream.h"
#include "nvim/event/wstream.h"
-#include "nvim/log.h"
+#include "nvim/macros.h"
#include "nvim/memory.h"
-#include "nvim/vim.h"
#define DEFAULT_MAXMEM 1024 * 1024 * 2000
diff --git a/src/nvim/event/wstream.h b/src/nvim/event/wstream.h
index d599d29913..ef1311c619 100644
--- a/src/nvim/event/wstream.h
+++ b/src/nvim/event/wstream.h
@@ -2,12 +2,15 @@
#define NVIM_EVENT_WSTREAM_H
#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
#include <uv.h>
#include "nvim/event/loop.h"
#include "nvim/event/stream.h"
+struct wbuffer;
+
typedef struct wbuffer WBuffer;
typedef void (*wbuffer_data_finalizer)(void *data);