From a1dd70b1d0e9ef155c81eeb249f137e763482d10 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sun, 2 Nov 2014 16:37:08 -0300 Subject: event: Reintroduce the immediate event queue Commit @264e0d872c("Remove automatic event deferral") removed the immediate event queue because event deferral now had to be explicit. The problem is that while some events don't need to be deferred, they still can result in recursive `event_poll` calls, and recursion is not supported by libuv. Examples of those are msgpack-rpc requests while a server->client request is pending, or signals which can call `mch_exit`(and that will result in `uv_run` calls). To fix the problem, this reintroduces the immediate event queue for events that can potentially result in event loop recursion. The non-deferred events are still processed in `event_poll`, but only after `uv_run` returns. --- src/nvim/os/signal.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src/nvim/os/signal.c') 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 +#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; } } + -- cgit From 75a5674cd2d0921400d2d2c7a9ce9701c58c5b25 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sun, 2 Nov 2014 16:37:31 -0300 Subject: event: Ensure the event loop has been cleaned up in event_teardown - Add input_teardown/signal_teardown to take care of closing signal/stdin handles. - Call those functions in event_teardown, and ensure there are no active handles by entering an infinite loop when there are unclosed handles(think of this as an assertion that can't go unoticed on travis). - Move event_teardown call to the end of mch_exit. That is required because event_poll may still be called in that function. --- src/nvim/os/signal.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/nvim/os/signal.c') diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c index d913df4cbf..cf8ba85ed5 100644 --- a/src/nvim/os/signal.c +++ b/src/nvim/os/signal.c @@ -55,6 +55,20 @@ void signal_init(void) #endif } +void signal_teardown(void) +{ + signal_stop(); + uv_close((uv_handle_t *)&sint, NULL); + uv_close((uv_handle_t *)&spipe, NULL); + uv_close((uv_handle_t *)&shup, NULL); + uv_close((uv_handle_t *)&squit, NULL); + uv_close((uv_handle_t *)&sterm, NULL); + uv_close((uv_handle_t *)&swinch, NULL); +#ifdef SIGPWR + uv_close((uv_handle_t *)&spwr, NULL); +#endif +} + void signal_stop(void) { uv_signal_stop(&sint); -- cgit