diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-12-09 19:13:13 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-12-09 19:13:13 +0100 |
commit | 620ca2da372dc9c892022faff83d363c67cc5c45 (patch) | |
tree | f1315ceb93d6cdee927169ee0e349a3b352dcbb5 | |
parent | 05684310a53c8a4804441c1c6f8b7fc9e8194940 (diff) |
patch 8.0.1381: ch_readraw() waits for NL if channel mode is NLv8.0.1381
Problem: ch_readraw() waits for NL if channel mode is NL.
Solution: Pass a "raw" flag to channel_read_block(). (Yasuhiro Matsumoto)
-rw-r--r-- | src/channel.c | 26 | ||||
-rw-r--r-- | src/proto/channel.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_channel.vim | 27 | ||||
-rw-r--r-- | src/testdir/test_channel_pipe.py | 4 | ||||
-rw-r--r-- | src/version.c | 4 |
5 files changed, 52 insertions, 10 deletions
diff --git a/src/channel.c b/src/channel.c index 8fc705058a..f7eded21e2 100644 --- a/src/channel.c +++ b/src/channel.c @@ -3313,11 +3313,12 @@ channel_read(channel_T *channel, ch_part_T part, char *func) /* * Read from RAW or NL "channel"/"part". Blocks until there is something to * read or the timeout expires. + * When "raw" is TRUE don't block waiting on a NL. * Returns what was read in allocated memory. * Returns NULL in case of error or timeout. */ - char_u * -channel_read_block(channel_T *channel, ch_part_T part, int timeout) + static char_u * +channel_read_block(channel_T *channel, ch_part_T part, int timeout, int raw) { char_u *buf; char_u *msg; @@ -3327,7 +3328,7 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout) readq_T *node; ch_log(channel, "Blocking %s read, timeout: %d msec", - mode == MODE_RAW ? "RAW" : "NL", timeout); + mode == MODE_RAW ? "RAW" : "NL", timeout); while (TRUE) { @@ -3340,6 +3341,10 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout) break; if (channel_collapse(channel, part, mode == MODE_NL) == OK) continue; + /* If not blocking or nothing more is coming then return what we + * have. */ + if (raw || fd == INVALID_FD) + break; } /* Wait for up to the channel timeout. */ @@ -3366,11 +3371,16 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout) nl = channel_first_nl(node); /* Convert NUL to NL, the internal representation. */ - for (p = buf; p < nl && p < buf + node->rq_buflen; ++p) + for (p = buf; (nl == NULL || p < nl) && p < buf + node->rq_buflen; ++p) if (*p == NUL) *p = NL; - if (nl + 1 == buf + node->rq_buflen) + if (nl == NULL) + { + /* must be a closed channel with missing NL */ + msg = channel_get(channel, part); + } + else if (nl + 1 == buf + node->rq_buflen) { /* get the whole buffer */ msg = channel_get(channel, part); @@ -3513,7 +3523,8 @@ common_channel_read(typval_T *argvars, typval_T *rettv, int raw) timeout = opt.jo_timeout; if (raw || mode == MODE_RAW || mode == MODE_NL) - rettv->vval.v_string = channel_read_block(channel, part, timeout); + rettv->vval.v_string = channel_read_block(channel, part, + timeout, raw); else { if (opt.jo_set & JO_ID) @@ -3955,7 +3966,8 @@ ch_raw_common(typval_T *argvars, typval_T *rettv, int eval) timeout = opt.jo_timeout; else timeout = channel_get_timeout(channel, part_read); - rettv->vval.v_string = channel_read_block(channel, part_read, timeout); + rettv->vval.v_string = channel_read_block(channel, part_read, + timeout, TRUE); } free_job_options(&opt); } diff --git a/src/proto/channel.pro b/src/proto/channel.pro index 40742adad3..3738edcee2 100644 --- a/src/proto/channel.pro +++ b/src/proto/channel.pro @@ -31,7 +31,6 @@ void channel_close(channel_T *channel, int invoke_close_cb); void channel_close_in(channel_T *channel); void channel_clear(channel_T *channel); void channel_free_all(void); -char_u *channel_read_block(channel_T *channel, ch_part_T part, int timeout); void common_channel_read(typval_T *argvars, typval_T *rettv, int raw); channel_T *channel_fd2channel(sock_T fd, ch_part_T *partp); void channel_handle_events(int only_keep_open); diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim index 034bd39778..1859afc5b8 100644 --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -515,7 +515,7 @@ func Test_nl_pipe() call assert_equal("AND this", ch_readraw(handle)) call ch_sendraw(handle, "split this line\n") - call assert_equal("this linethis linethis line", ch_readraw(handle)) + call assert_equal("this linethis linethis line", ch_read(handle)) let reply = ch_evalraw(handle, "quit\n") call assert_equal("Goodbye!", reply) @@ -1266,6 +1266,31 @@ func Test_read_in_close_cb() endtry endfunc +" Use channel in NL mode but received text does not end in NL. +func Test_read_in_close_cb_incomplete() + if !has('job') + return + endif + call ch_log('Test_read_in_close_cb_incomplete()') + + let g:Ch_received = '' + func! CloseHandler(chan) + while ch_status(a:chan, {'part': 'out'}) == 'buffered' + let g:Ch_received .= ch_read(a:chan) + endwhile + endfunc + let job = job_start(s:python . " test_channel_pipe.py incomplete", + \ {'close_cb': 'CloseHandler'}) + call assert_equal("run", job_status(job)) + try + call WaitFor('g:Ch_received != ""') + call assert_equal('incomplete', g:Ch_received) + finally + call job_stop(job) + delfunc CloseHandler + endtry +endfunc + func Test_out_cb_lambda() if !has('job') return diff --git a/src/testdir/test_channel_pipe.py b/src/testdir/test_channel_pipe.py index a67a81a853..940378624b 100644 --- a/src/testdir/test_channel_pipe.py +++ b/src/testdir/test_channel_pipe.py @@ -14,6 +14,10 @@ if __name__ == "__main__": if sys.argv[1].startswith("err"): print(sys.argv[1], file=sys.stderr) sys.stderr.flush() + elif sys.argv[1].startswith("incomplete"): + print(sys.argv[1], end='') + sys.stdout.flush() + sys.exit(0) else: print(sys.argv[1]) sys.stdout.flush() diff --git a/src/version.c b/src/version.c index fad2fdc05b..8ae4769504 100644 --- a/src/version.c +++ b/src/version.c @@ -772,7 +772,9 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ - 1390, + 1381, +/**/ + 1380, /**/ 1379, /**/ |