]> granicus.if.org Git - vim/commitdiff
patch 8.0.1381: ch_readraw() waits for NL if channel mode is NL v8.0.1381
authorBram Moolenaar <Bram@vim.org>
Sat, 9 Dec 2017 18:13:13 +0000 (19:13 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 9 Dec 2017 18:13:13 +0000 (19:13 +0100)
Problem:    ch_readraw() waits for NL if channel mode is NL.
Solution:   Pass a "raw" flag to channel_read_block(). (Yasuhiro Matsumoto)

src/channel.c
src/proto/channel.pro
src/testdir/test_channel.vim
src/testdir/test_channel_pipe.py
src/version.c

index 8fc705058a1fc8ed493afc92d8ea7140e4fe7377..f7eded21e2ef4295bf8f9b574a40a5f75b7fa379 100644 (file)
@@ -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);
 }
index 40742adad380949ed3f1aadfec378a304175b963..3738edcee252bc5de5ddc4f2c5a9d49219af4b6d 100644 (file)
@@ -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);
index 034bd3977807e806ab8fea2414c0f5e523bf997d..1859afc5b8a321d430983924bc8452eae69fe110 100644 (file)
@@ -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
index a67a81a85389b6406e830cf1182b7989b49cef53..940378624be624e4066ffc095f2d8b271c1746fd 100644 (file)
@@ -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()
index fad2fdc05b71179540811cc91ee46d4cf6ef5dbd..8ae4769504cf01b18858c1a6a98854a709b11e79 100644 (file)
@@ -772,7 +772,9 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
-    1390,
+    1381,
+/**/
+    1380,
 /**/
     1379,
 /**/