aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/eval.c2
-rw-r--r--src/nvim/msgpack_rpc/channel.c24
-rw-r--r--src/nvim/os/event.c39
-rw-r--r--src/nvim/os/signal.c22
4 files changed, 54 insertions, 33 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 6b6f008a44..caa936ba13 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -19541,7 +19541,7 @@ char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags)
event_push((Event) { \
.handler = on_job_event, \
.data = event_data \
- }); \
+ }, true); \
} while(0)
static void on_job_stdout(RStream *rstream, void *data, bool eof)
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 58e1f403ec..10d180b3b7 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -435,13 +435,7 @@ static void handle_request(Channel *channel, msgpack_object *request)
Array args = ARRAY_DICT_INIT;
msgpack_rpc_to_array(request->via.array.ptr + 3, &args);
-
- if (kv_size(channel->call_stack) || !handler.defer) {
- call_request_handler(channel, handler, args, request_id);
- return;
- }
-
- // Defer calling the request handler.
+ bool defer = (!kv_size(channel->call_stack) && handler.defer);
RequestEvent *event_data = kmp_alloc(RequestEventPool, request_event_pool);
event_data->channel = channel;
event_data->handler = handler;
@@ -450,21 +444,16 @@ static void handle_request(Channel *channel, msgpack_object *request)
event_push((Event) {
.handler = on_request_event,
.data = event_data
- });
+ }, defer);
}
static void on_request_event(Event event)
{
RequestEvent *e = event.data;
- call_request_handler(e->channel, e->handler, e->args, e->request_id);
- kmp_free(RequestEventPool, request_event_pool, e);
-}
-
-static void call_request_handler(Channel *channel,
- MsgpackRpcRequestHandler handler,
- Array args,
- uint64_t request_id)
-{
+ Channel *channel = e->channel;
+ MsgpackRpcRequestHandler handler = e->handler;
+ Array args = e->args;
+ uint64_t request_id = e->request_id;
Error error = ERROR_INIT;
Object result = handler.fn(channel->id, request_id, args, &error);
// send the response
@@ -477,6 +466,7 @@ static void call_request_handler(Channel *channel,
&out_buffer));
// All arguments were freed already, but we still need to free the array
free(args.items);
+ kmp_free(RequestEventPool, request_event_pool, e);
}
static bool channel_write(Channel *channel, WBuffer *buffer)
diff --git a/src/nvim/os/event.c b/src/nvim/os/event.c
index 657f1edad0..e09303e505 100644
--- a/src/nvim/os/event.c
+++ b/src/nvim/os/event.c
@@ -35,18 +35,24 @@ typedef struct {
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/event.c.generated.h"
#endif
-static klist_t(Event) *deferred_events;
+// deferred_events: Events that should be processed as the K_EVENT special key
+// immediate_events: Events that should be processed after exiting libuv event
+// loop(to avoid recursion), but before returning from
+// `event_poll`
+static klist_t(Event) *deferred_events, *immediate_events;
void event_init(void)
{
// Initialize the event queues
deferred_events = kl_init(Event);
+ immediate_events = kl_init(Event);
// early msgpack-rpc initialization
msgpack_rpc_init_method_table();
msgpack_rpc_helpers_init();
wstream_init();
// Initialize input events
input_init();
+ input_start();
// Timer to wake the event loop if a timeout argument is passed to
// `event_poll`
// Signals
@@ -65,20 +71,19 @@ void event_teardown(void)
channel_teardown();
job_teardown();
server_teardown();
+ input_stop();
}
// Wait for some event
void event_poll(int ms)
{
- uv_run_mode run_mode = UV_RUN_ONCE;
-
static int recursive = 0;
- if (!(recursive++)) {
- // Only needs to start the libuv handle the first time we enter here
- input_start();
+ if (recursive++) {
+ abort(); // Should not re-enter uv_run
}
+ uv_run_mode run_mode = UV_RUN_ONCE;
uv_timer_t timer;
uv_prepare_t timer_prepare;
TimerData timer_data = {.ms = ms, .timed_out = false, .timer = &timer};
@@ -101,18 +106,18 @@ void event_poll(int ms)
loop(run_mode);
- if (!(--recursive)) {
- // Again, only stop when we leave the top-level invocation
- input_stop();
- }
-
if (ms > 0) {
// Ensure the timer-related handles are closed and run the event loop
// once more to let libuv perform it's cleanup
+ uv_timer_stop(&timer);
+ uv_prepare_stop(&timer_prepare);
uv_close((uv_handle_t *)&timer, NULL);
uv_close((uv_handle_t *)&timer_prepare, NULL);
loop(UV_RUN_NOWAIT);
}
+
+ recursive--; // Can re-enter uv_run now
+ process_events_from(immediate_events);
}
bool event_has_deferred(void)
@@ -121,17 +126,21 @@ bool event_has_deferred(void)
}
// Queue an event
-void event_push(Event event)
+void event_push(Event event, bool deferred)
{
- *kl_pushp(Event, deferred_events) = event;
+ *kl_pushp(Event, deferred ? deferred_events : immediate_events) = event;
}
-
void event_process(void)
{
+ process_events_from(deferred_events);
+}
+
+static void process_events_from(klist_t(Event) *queue)
+{
Event event;
- while (kl_shift(Event, deferred_events, &event) == 0) {
+ while (kl_shift(Event, queue, &event) == 0) {
event.handler(event);
}
}
diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c
index 36f7b37c48..d913df4cbf 100644
--- a/src/nvim/os/signal.c
+++ b/src/nvim/os/signal.c
@@ -2,6 +2,8 @@
#include <uv.h>
+#include "nvim/lib/klist.h"
+
#include "nvim/types.h"
#include "nvim/ascii.h"
#include "nvim/vim.h"
@@ -13,6 +15,11 @@
#include "nvim/misc1.h"
#include "nvim/misc2.h"
#include "nvim/os/signal.h"
+#include "nvim/os/event.h"
+
+#define SignalEventFreer(x)
+KMEMPOOL_INIT(SignalEventPool, int, SignalEventFreer)
+kmempool_t(SignalEventPool) *signal_event_pool = NULL;
static uv_signal_t sint, spipe, shup, squit, sterm, swinch;
#ifdef SIGPWR
@@ -26,6 +33,7 @@ static bool rejecting_deadly;
#endif
void signal_init(void)
{
+ signal_event_pool = kmp_init(SignalEventPool);
uv_signal_init(uv_default_loop(), &sint);
uv_signal_init(uv_default_loop(), &spipe);
uv_signal_init(uv_default_loop(), &shup);
@@ -113,6 +121,19 @@ static void deadly_signal(int signum)
static void signal_cb(uv_signal_t *handle, int signum)
{
+ int *n = kmp_alloc(SignalEventPool, signal_event_pool);
+ *n = signum;
+ event_push((Event) {
+ .handler = on_signal_event,
+ .data = n
+ }, false);
+}
+
+static void on_signal_event(Event event)
+{
+ int signum = *((int *)event.data);
+ kmp_free(SignalEventPool, signal_event_pool, event.data);
+
switch (signum) {
case SIGINT:
got_int = true;
@@ -142,3 +163,4 @@ static void signal_cb(uv_signal_t *handle, int signum)
break;
}
}
+