aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoroni-link <knil.ino@gmail.com>2015-08-11 13:40:07 +0200
committerJustin M. Keyes <justinkz@gmail.com>2015-08-11 09:36:06 -0400
commitc6af09c5663f31a43bbf02f16089437fe41574f7 (patch)
tree806945c59fb2135270147426a3ebf63d47b0609a
parent7d9472ab1b7dc4eb2bb838fb8febcc7a1aab649d (diff)
downloadrneovim-c6af09c5663f31a43bbf02f16089437fe41574f7.tar.gz
rneovim-c6af09c5663f31a43bbf02f16089437fe41574f7.tar.bz2
rneovim-c6af09c5663f31a43bbf02f16089437fe41574f7.zip
shell.c: A full RBuffer with no NL can freeze shell output. #3156
out_data_cb() can return without emptying the full RBuffer (no NL was seen). Because the shell output stream is stopped until space in the Rbuffer is freed up, no more shell output is written. To prevent this, output the full RBuffer when write_output() did not write anything. write_output() can also process the same RBuffer content more than once, if no NL was seen. To prevent NUL bytes from producing new lines (if lines are not written to a buffer), translate NUL to SOH(1). Fixes #2983
-rw-r--r--src/nvim/os/shell.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index e0d67d4951..b9c5db4261 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -297,14 +297,22 @@ static void system_data_cb(Stream *stream, RBuffer *buf, void *data, bool eof)
static void out_data_cb(Stream *stream, RBuffer *buf, void *data, bool eof)
{
- RBUFFER_UNTIL_EMPTY(buf, ptr, len) {
- size_t written = write_output(ptr, len, false,
- eof && len <= rbuffer_size(buf));
- if (written) {
- rbuffer_consumed(buf, written);
- } else {
- break;
- }
+ size_t cnt;
+ char *ptr = rbuffer_read_ptr(buf, &cnt);
+
+ if (!cnt) {
+ return;
+ }
+
+ size_t written = write_output(ptr, cnt, false, eof);
+ // No output written, force emptying the Rbuffer if it is full.
+ if (!written && rbuffer_size(buf) == rbuffer_capacity(buf)) {
+ screen_del_lines(0, 0, 1, (int)Rows, NULL);
+ screen_puts_len((char_u *)ptr, (int)cnt, (int)Rows - 1, 0, 0);
+ written = cnt;
+ }
+ if (written) {
+ rbuffer_consumed(buf, written);
}
}
@@ -421,6 +429,7 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer,
if (!output) {
return 0;
}
+ char replacement_NUL = to_buffer ? NL : 1;
char *start = output;
size_t off = 0;
@@ -428,9 +437,10 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer,
while (off < remaining) {
if (output[off] == NL) {
// Insert the line
- output[off] = NUL;
if (to_buffer) {
- ml_append(curwin->w_cursor.lnum++, (char_u *)output, 0, false);
+ output[off] = NUL;
+ ml_append(curwin->w_cursor.lnum++, (char_u *)output, (int)off + 1,
+ false);
} else {
screen_del_lines(0, 0, 1, (int)Rows, NULL);
screen_puts_len((char_u *)output, (int)off, lastrow, 0, 0);
@@ -444,7 +454,7 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer,
if (output[off] == NUL) {
// Translate NUL to NL
- output[off] = NL;
+ output[off] = replacement_NUL;
}
off++;
}