aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoroni-link <knil.ino@gmail.com>2015-08-05 07:54:44 +0200
committerJustin M. Keyes <justinkz@gmail.com>2015-08-05 11:17:08 -0400
commitb732a27c4e568ff0d56c74348e1c3fdf38364b81 (patch)
tree38fab29a7027b2962dc0a799ad2a0da0908d4fbc
parent2e1a80563b56ecfee0306bf724b264115ca751a1 (diff)
downloadrneovim-b732a27c4e568ff0d56c74348e1c3fdf38364b81.tar.gz
rneovim-b732a27c4e568ff0d56c74348e1c3fdf38364b81.tar.bz2
rneovim-b732a27c4e568ff0d56c74348e1c3fdf38364b81.zip
channel.c: Only free a channel after close callbacks are executed #3132
parse_msgpack() closes a channel's stream on EOF error and the stream's close callback close_cb() is queued for the next libuv loop iteration. When parse_msgpack() returns, it has freed the channel and the queued stream callback will access this freed memory. To prevent this, increase the channel's reference count and let the stream's close callback call decref(). Fixes #3128
-rw-r--r--src/nvim/msgpack_rpc/channel.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 861614f147..eee662dd9c 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -153,6 +153,9 @@ void channel_from_connection(SocketWatcher *watcher)
{
Channel *channel = register_channel(kChannelTypeSocket);
socket_watcher_accept(watcher, &channel->data.stream, channel);
+ incref(channel); // close channel only after the stream is closed
+ channel->data.stream.internal_close_cb = close_cb;
+ channel->data.stream.internal_data = channel;
wstream_init(&channel->data.stream, 0);
rstream_init(&channel->data.stream, CHANNEL_BUFFER_SIZE);
rstream_start(&channel->data.stream, parse_msgpack);
@@ -636,7 +639,7 @@ static void close_channel(Channel *channel)
switch (channel->type) {
case kChannelTypeSocket:
- stream_close(&channel->data.stream, close_cb);
+ stream_close(&channel->data.stream, NULL);
break;
case kChannelTypeProc:
if (!channel->data.process.uvproc.process.closed) {
@@ -685,7 +688,7 @@ static void free_channel(Channel *channel)
static void close_cb(Stream *stream, void *data)
{
- xfree(data);
+ decref(data);
}
static Channel *register_channel(ChannelType type)