From b732a27c4e568ff0d56c74348e1c3fdf38364b81 Mon Sep 17 00:00:00 2001 From: oni-link Date: Wed, 5 Aug 2015 07:54:44 +0200 Subject: [PATCH] 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 --- src/nvim/msgpack_rpc/channel.c | 7 +++++-- 1 file 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)