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)
diff --git a/src/channel.c b/src/channel.c
index 8f0577f..f6ffcd6 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -80,11 +80,23 @@
static int
fd_write(sock_T fd, char *buf, size_t len)
{
- HANDLE h = (HANDLE)fd;
- DWORD nwrite;
+ HANDLE h = (HANDLE)fd;
+ DWORD nwrite;
+ OVERLAPPED ov;
- if (!WriteFile(h, buf, (DWORD)len, &nwrite, NULL))
- return -1;
+ // 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 @@
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 @@
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