]> granicus.if.org Git - vim/commitdiff
patch 8.1.0889: MS-Windows: a channel write may hang v8.1.0889
authorBram Moolenaar <Bram@vim.org>
Sun, 10 Feb 2019 21:23:26 +0000 (22:23 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 10 Feb 2019 21:23:26 +0000 (22:23 +0100)
Problem:    MS-Windows: a channel write may hang.
Solution:   Check for WriteFile() not writing anything. (Yasuhiro Matsumoto,
            closes #3920)

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

index 34a1fc3e039e1f561b24f6d68e4828f7ccd14af6..d728c77d9ffdae0deb0915e3fe74770d644e57f9 100644 (file)
@@ -91,9 +91,10 @@ fd_write(sock_T fd, char *buf, size_t len)
            size = MAX_NAMED_PIPE_SIZE;
        else
            size = (DWORD)todo;
-       // If the pipe overflows while the job does not read the data, WriteFile
-       // will block forever. This abandons the write.
+       // 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));
+       nwrite = 0;
        if (!WriteFile(h, buf + done, size, &nwrite, &ov))
        {
            DWORD err = GetLastError();
@@ -104,6 +105,10 @@ fd_write(sock_T fd, char *buf, size_t len)
                return -1;
            FlushFileBuffers(h);
        }
+       else if (nwrite == 0)
+           // WriteFile() returns TRUE but did not write anything. This causes
+           // a hang, so bail out.
+           break;
        todo -= nwrite;
        done += nwrite;
     }
index 2aef3e1dc4d82db24ecc45d82e9aa6cbf8c26e41..becd5484f91574c547482fa733fcff9d10c5355a 100644 (file)
@@ -2003,6 +2003,20 @@ func Test_raw_large_data()
   endtry
 endfunc
 
+func Test_no_hang_windows()
+  if !has('job') || !has('win32')
+    return
+  endif
+
+  try
+    let job = job_start(s:python . " test_channel_pipe.py busy",
+          \ {'mode': 'raw', 'drop': 'never', 'noblock': 0})
+    call assert_fails('call ch_sendraw(job, repeat("X", 80000))', 'E631:')
+  finally
+    call job_stop(job)
+  endtry
+endfunc
+
 func Test_job_exitval_and_termsig()
   if !has('unix')
     return
index 810a8e303286957d33701d383abdb6a79b3e5820..5caffcbf9e345b1ab80113065725aff8edb73268 100644 (file)
@@ -18,6 +18,9 @@ if __name__ == "__main__":
             print(sys.argv[1], end='')
             sys.stdout.flush()
             sys.exit(0)
+        elif sys.argv[1].startswith("busy"):
+            time.sleep(100)
+            sys.exit(0)
         else:
             print(sys.argv[1])
             sys.stdout.flush()
index e31b7cace66afe93b2a1a9e4c53c75f659b342da..a990f2c3c1fc0537970ae39125ee9d176c6d0ffe 100644 (file)
@@ -783,6 +783,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    889,
 /**/
     888,
 /**/