]> granicus.if.org Git - vim/commitdiff
patch 8.1.0818: MS-Windows: cannot send large data with ch_sendraw() v8.1.0818
authorBram Moolenaar <Bram@vim.org>
Thu, 24 Jan 2019 22:11:49 +0000 (23:11 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 24 Jan 2019 22:11:49 +0000 (23:11 +0100)
Problem:    MS-Windows: cannot send large data with ch_sendraw().
Solution:   Split write into several WriteFile() calls. (Yasuhiro Matsumoto,
            closes #3823)

src/channel.c
src/os_win32.c
src/testdir/test_channel.vim
src/testdir/test_channel_pipe.py
src/version.c
src/vim.h

index 3a80748a1259123102235abcf3e57031776eb32c..b013a8558d361653d260bc47b4a10e1654bc5203 100644 (file)
@@ -80,24 +80,34 @@ fd_read(sock_T fd, char *buf, size_t len)
     static int
 fd_write(sock_T fd, char *buf, size_t len)
 {
+    size_t     todo = len;
     HANDLE     h = (HANDLE)fd;
-    DWORD      nwrite;
+    DWORD      nwrite, size, done = 0;
     OVERLAPPED ov;
 
-    // If the pipe overflows while the job does not read the data, WriteFile
-    // will block forever. This abandons the write.
-    memset(&ov, 0, sizeof(ov));
-    if (!WriteFile(h, buf, (DWORD)len, &nwrite, &ov))
+    while (todo > 0)
     {
-       DWORD err = GetLastError();
+       if (todo > MAX_NAMED_PIPE_SIZE)
+           size = MAX_NAMED_PIPE_SIZE;
+       else
+           size = todo;
+       // If the pipe overflows while the job does not read the data, WriteFile
+       // will block forever. This abandons the write.
+       memset(&ov, 0, sizeof(ov));
+       if (!WriteFile(h, buf + done, size, &nwrite, &ov))
+       {
+           DWORD err = GetLastError();
 
-       if (err != ERROR_IO_PENDING)
-           return -1;
-       if (!GetOverlappedResult(h, &ov, &nwrite, FALSE))
-           return -1;
-       FlushFileBuffers(h);
+           if (err != ERROR_IO_PENDING)
+               return -1;
+           if (!GetOverlappedResult(h, &ov, &nwrite, FALSE))
+               return -1;
+           FlushFileBuffers(h);
+       }
+       todo -= nwrite;
+       done += nwrite;
     }
-    return (int)nwrite;
+    return (int)done;
 }
 
     static void
index 8966053b837c0e3b1341a6b67ab78021513b3b68..6a127a44a3815be77a06e14bcb0b97a4284f835d 100644 (file)
@@ -5369,7 +5369,7 @@ create_pipe_pair(HANDLE handles[2])
            name,
            PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
            PIPE_TYPE_BYTE | PIPE_NOWAIT,
-           1, 65535, 0, 0, NULL);
+           1, MAX_NAMED_PIPE_SIZE, 0, 0, NULL);
 
     if (handles[1] == INVALID_HANDLE_VALUE)
        return FALSE;
index 15ca9ddbb52508c4c52a56efe8197aef9befd879..e7fcf95826d012634012e8191bc80fad52425e85 100644 (file)
@@ -1980,3 +1980,21 @@ func Test_job_start_in_timer()
   unlet! g:val
   unlet! g:job
 endfunc
+
+func Test_raw_large_data()
+  try
+    let g:out = ''
+    let job = job_start(s:python . " test_channel_pipe.py",
+         \ {'mode': 'raw', 'drop': 'never', 'noblock': 1,
+      \  'callback': {ch, msg -> execute('let g:out .= msg')}})
+
+    let want = repeat('X', 79999) . "\n"
+    call ch_sendraw(job, want)
+    let g:Ch_job = job
+    call WaitForAssert({-> assert_equal("dead", job_status(g:Ch_job))})
+    call assert_equal(want, substitute(g:out, '\r', '', 'g'))
+  finally
+    call job_stop(job)
+    unlet g:out
+  endtry
+endfunc
index 940378624be624e4066ffc095f2d8b271c1746fd..810a8e303286957d33701d383abdb6a79b3e5820 100644 (file)
@@ -56,4 +56,8 @@ if __name__ == "__main__":
         if typed.startswith("doubleerr "):
             print(typed[10:-1] + "\nAND " + typed[10:-1], file=sys.stderr)
             sys.stderr.flush()
+        if typed.startswith("XXX"):
+            print(typed, end='')
+            sys.stderr.flush()
+            break
 
index 532b449ddc059c002fa650520b4db35bc04a348a..4beae276fd41a5eb549ac1c6b1439095b83fee16 100644 (file)
@@ -787,6 +787,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    818,
 /**/
     817,
 /**/
index 55cb69389c9a857c0aa81721d7031bc7331dac44..5bd1b3c940828d073d8e960e0d2c9f531bb1aa2a 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -2467,6 +2467,10 @@ typedef enum {
 # define MAX_OPEN_CHANNELS 0
 #endif
 
+#if defined(WIN32)
+# define MAX_NAMED_PIPE_SIZE 65535
+#endif
+
 /* Options for json_encode() and json_decode. */
 #define JSON_JS                1   /* use JS instead of JSON */
 #define JSON_NO_NONE   2   /* v:none item not allowed */