aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/msgpack_rpc/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/msgpack_rpc/channel.c')
-rw-r--r--src/nvim/msgpack_rpc/channel.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 79a9e1082d..b4f39c4c61 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -26,6 +26,7 @@
#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/helpers.h"
+#include "nvim/msgpack_rpc/unpacker.h"
#include "nvim/os/input.h"
#include "nvim/os_unix.h"
#include "nvim/ui.h"
@@ -113,7 +114,8 @@ bool rpc_send_event(uint64_t id, const char *name, Array args)
/// @param args Array with method arguments
/// @param[out] error True if the return value is an error
/// @return Whatever the remote method returned
-Object rpc_send_call(uint64_t id, const char *method_name, Array args, Error *err)
+Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem *result_mem,
+ Error *err)
{
Channel *channel = NULL;
@@ -130,7 +132,7 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, Error *er
send_request(channel, request_id, method_name, args);
// Push the frame
- ChannelCallFrame frame = { request_id, false, false, NIL };
+ ChannelCallFrame frame = { request_id, false, false, NIL, NULL };
kv_push(rpc->call_stack, &frame);
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, frame.returned);
(void)kv_pop(rpc->call_stack);
@@ -155,11 +157,15 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, Error *er
api_set_error(err, kErrorTypeException, "%s", "unknown error");
}
- api_free_object(frame.result);
+ // frame.result was allocated in an arena
+ arena_mem_free(frame.result_mem, &rpc->unpacker->reuse_blk);
+ frame.result_mem = NULL;
}
channel_decref(channel);
+ *result_mem = frame.result_mem;
+
return frame.errored ? NIL : frame.result;
}
@@ -249,17 +255,17 @@ static void parse_msgpack(Channel *channel)
if (frame->errored) {
frame->result = p->error;
// TODO(bfredl): p->result should not even be decoded
- api_free_object(p->result);
+ // api_free_object(p->result);
} else {
frame->result = p->result;
}
+ frame->result_mem = arena_finish(&p->arena);
} else {
log_client_msg(channel->id, p->type == kMessageTypeRequest, p->handler.name);
Object res = p->result;
if (p->result.type != kObjectTypeArray) {
chan_close_with_error(channel, "msgpack-rpc request args has to be an array", LOGLVL_ERR);
- api_free_object(p->result);
return;
}
Array arg = res.data.array;
@@ -282,7 +288,7 @@ static void handle_request(Channel *channel, Unpacker *p, Array args)
if (!p->handler.fn) {
send_error(channel, p->type, p->request_id, p->unpack_error.msg);
api_clear_error(&p->unpack_error);
- api_free_array(args);
+ arena_mem_free(arena_finish(&p->arena), &p->reuse_blk);
return;
}
@@ -291,6 +297,7 @@ static void handle_request(Channel *channel, Unpacker *p, Array args)
evdata->channel = channel;
evdata->handler = p->handler;
evdata->args = args;
+ evdata->used_mem = arena_finish(&p->arena);
evdata->request_id = p->request_id;
channel_incref(channel);
if (p->handler.fast) {
@@ -346,7 +353,8 @@ static void request_event(void **argv)
}
free_ret:
- api_free_array(e->args);
+ // e->args is allocated in an arena
+ arena_mem_free(e->used_mem, &channel->rpc.unpacker->reuse_blk);
channel_decref(channel);
xfree(e);
api_clear_error(&error);
@@ -523,6 +531,7 @@ static void exit_event(void **argv)
void rpc_free(Channel *channel)
{
remote_ui_disconnect(channel->id);
+ unpacker_teardown(channel->rpc.unpacker);
xfree(channel->rpc.unpacker);
// Unsubscribe from all events
@@ -543,7 +552,6 @@ static void chan_close_with_error(Channel *channel, char *msg, int loglevel)
ChannelCallFrame *frame = kv_A(channel->rpc.call_stack, i);
frame->returned = true;
frame->errored = true;
- api_free_object(frame->result);
frame->result = STRING_OBJ(cstr_to_string(msg));
}