diff src/channel.c @ 15539:ba876ced4f1f v8.1.0777

patch 8.1.0777: Win32: using pipes for channel does not work well commit https://github.com/vim/vim/commit/b091f30bf38eacb31b9d8c97c82c7e0af9866301 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jan 19 14:37:00 2019 +0100 patch 8.1.0777: Win32: using pipes for channel does not work well Problem: Win32: using pipes for channel does not work well. Solution: Use a larger buffer and handle overlaps. (Yasuhiro Matsumoto, closes #3782)
author Bram Moolenaar <Bram@vim.org>
date Sat, 19 Jan 2019 14:45:06 +0100
parents 3ef31ce9d9f9
children d89c5b339c2a
line wrap: on
line diff
--- a/src/channel.c
+++ b/src/channel.c
@@ -80,11 +80,23 @@ fd_read(sock_T fd, char *buf, size_t len
     static int
 fd_write(sock_T fd, char *buf, size_t len)
 {
-    HANDLE h = (HANDLE)fd;
-    DWORD nwrite;
-
-    if (!WriteFile(h, buf, (DWORD)len, &nwrite, NULL))
-	return -1;
+    HANDLE	h = (HANDLE)fd;
+    DWORD	nwrite;
+    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))
+    {
+	DWORD err = GetLastError();
+
+	if (err != ERROR_IO_PENDING)
+	    return -1;
+	if (!GetOverlappedResult(h, &ov, &nwrite, FALSE))
+	    return -1;
+	FlushFileBuffers(h);
+    }
     return (int)nwrite;
 }
 
@@ -3168,20 +3180,7 @@ channel_wait(channel_T *channel, sock_T 
 	    if (r && nread > 0)
 		return CW_READY;
 	    if (r == 0)
-	    {
-		DWORD err = GetLastError();
-
-		if (err != ERROR_BAD_PIPE && err != ERROR_BROKEN_PIPE)
-		    return CW_ERROR;
-
-		if (channel->ch_named_pipe)
-		{
-		    DisconnectNamedPipe((HANDLE)fd);
-		    ConnectNamedPipe((HANDLE)fd, NULL);
-		}
-		else
-		    return CW_ERROR;
-	    }
+		return CW_ERROR;
 
 	    /* perhaps write some buffer lines */
 	    channel_write_any_lines();
@@ -3812,17 +3811,7 @@ channel_send(
 	if (part == PART_SOCK)
 	    res = sock_write(fd, (char *)buf, len);
 	else
-	{
 	    res = fd_write(fd, (char *)buf, len);
-#ifdef WIN32
-	    if (channel->ch_named_pipe && res < 0)
-	    {
-		DisconnectNamedPipe((HANDLE)fd);
-		ConnectNamedPipe((HANDLE)fd, NULL);
-	    }
-#endif
-
-	}
 	if (res < 0 && (errno == EWOULDBLOCK
 #ifdef EAGAIN
 			|| errno == EAGAIN