diff options
author | oni-link <knil.ino@gmail.com> | 2016-05-14 02:36:04 +0200 |
---|---|---|
committer | oni-link <knil.ino@gmail.com> | 2016-05-15 02:54:09 +0200 |
commit | 14ea366f249ab5966019bfd399f8be5547c45569 (patch) | |
tree | e41f6db916599bf48a7d758ece9f6261ff904d02 | |
parent | 1c83e9eb82ec150a3a3c201e8566ea383589b775 (diff) | |
download | rneovim-14ea366f249ab5966019bfd399f8be5547c45569.tar.gz rneovim-14ea366f249ab5966019bfd399f8be5547c45569.tar.bz2 rneovim-14ea366f249ab5966019bfd399f8be5547c45569.zip |
fixup: process.c: Prevent data loss for process output streams
* Get system buffer size for upper data limit. Otherwise data loss
if this buffer is too big.
* Test whether teardown needs special handling.
-rw-r--r-- | src/nvim/event/process.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 2e6511a167..23a60c3052 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -344,21 +344,36 @@ static void flush_stream(Process *proc, Stream *stream) return; } - // Limit amount of data we accept after process terminated. - size_t max_bytes = stream->num_bytes + rbuffer_capacity(stream->buffer); + // Maximal remaining data size of terminated process is system + // buffer size. + // Also helps with a child process that keeps the output streams open. If it + // keeps sending data, we only accept as much data as the system buffer size. + // Otherwise this would block cleanup/teardown. + int system_buffer_size = 0; + int err = uv_recv_buffer_size((uv_handle_t *)&stream->uv.pipe, + &system_buffer_size); + if (err) { + system_buffer_size = (int)rbuffer_capacity(stream->buffer); + } + + size_t max_bytes = stream->num_bytes + (size_t)system_buffer_size; + // Read remaining data. while (!stream->closed && stream->num_bytes < max_bytes) { // Remember number of bytes before polling size_t num_bytes = stream->num_bytes; // Poll for data and process the generated events. loop_poll_events(&loop, 0); - if (proc->events && !queue_empty(proc->events)) { - queue_process_events(proc->events); - } + queue_process_events(proc->events); // Stream can be closed if it is empty. if (num_bytes == stream->num_bytes) { + if (stream->read_cb) { + // Stream callback could miss EOF handling if a child keeps the stream + // open. + stream->read_cb(stream, stream->buffer, 0, stream->data, true); + } break; } } @@ -368,11 +383,8 @@ static void process_close_handles(void **argv) { Process *proc = argv[0]; - // Did our process forked a child that keeps the output streams open? - if (!process_is_tearing_down) { - flush_stream(proc, proc->out); - flush_stream(proc, proc->err); - } + flush_stream(proc, proc->out); + flush_stream(proc, proc->err); process_close_streams(proc); process_close(proc); |