diff options
| author | Thiago de Arruda <tpadilha84@gmail.com> | 2014-11-02 16:37:08 -0300 |
|---|---|---|
| committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-11-02 16:47:50 -0300 |
| commit | a1dd70b1d0e9ef155c81eeb249f137e763482d10 (patch) | |
| tree | d80bf394168eb84f6eaf3630d091a40cf2b9e379 /src/nvim/msgpack_rpc | |
| parent | e378965a4483881c3f737eed5c3d24cb1f305a62 (diff) | |
| download | rneovim-a1dd70b1d0e9ef155c81eeb249f137e763482d10.tar.gz rneovim-a1dd70b1d0e9ef155c81eeb249f137e763482d10.tar.bz2 rneovim-a1dd70b1d0e9ef155c81eeb249f137e763482d10.zip | |
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.
Diffstat (limited to 'src/nvim/msgpack_rpc')
| -rw-r--r-- | src/nvim/msgpack_rpc/channel.c | 24 |
1 files changed, 7 insertions, 17 deletions
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) |