aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoroni-link <knil.ino@gmail.com>2015-08-15 11:36:14 +0200
committerJustin M. Keyes <justinkz@gmail.com>2015-08-16 14:09:29 -0400
commitdb7b970057c92127624ebafa7affaf77fdff6750 (patch)
tree18534593b69f97f2e0cda79e0631f3320aa92eec
parent2bd3351c37bb916086f791b3f0e8bef960ce7b25 (diff)
downloadrneovim-db7b970057c92127624ebafa7affaf77fdff6750.tar.gz
rneovim-db7b970057c92127624ebafa7affaf77fdff6750.tar.bz2
rneovim-db7b970057c92127624ebafa7affaf77fdff6750.zip
rstream.c: Prevent stream closing if a read event is still queued. #3172
Processing a stream's output can be queued. If stream_close() is called before the queue is processed, the RBuffer containing the stream's data is freed and the next read event would try to access freed memory. To fix this behavior, use the stream's pending requests counter.
-rw-r--r--src/nvim/event/rstream.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/nvim/event/rstream.c b/src/nvim/event/rstream.c
index 0a720bb852..9f3fbc25ff 100644
--- a/src/nvim/event/rstream.c
+++ b/src/nvim/event/rstream.c
@@ -177,10 +177,25 @@ static void read_event(void **argv)
bool eof = (uintptr_t)argv[2];
stream->read_cb(stream, stream->buffer, count, stream->data, eof);
}
+ stream->pending_reqs--;
+ if (stream->closed && !stream->pending_reqs) {
+ stream_close_handle(stream);
+ }
}
static void invoke_read_cb(Stream *stream, size_t count, bool eof)
{
- CREATE_EVENT(stream->events, read_event, 3, stream,
- (void *)(uintptr_t *)count, (void *)(uintptr_t)eof);
+ if (stream->closed) {
+ return;
+ }
+
+ // Don't let the stream be closed before the event is processed.
+ stream->pending_reqs++;
+
+ CREATE_EVENT(stream->events,
+ read_event,
+ 3,
+ stream,
+ (void *)(uintptr_t *)count,
+ (void *)(uintptr_t)eof);
}