]> granicus.if.org Git - vim/commitdiff
patch 8.1.0777: Win32: using pipes for channel does not work well v8.1.0777
authorBram Moolenaar <Bram@vim.org>
Sat, 19 Jan 2019 13:37:00 +0000 (14:37 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 19 Jan 2019 13:37:00 +0000 (14:37 +0100)
Problem:    Win32: using pipes for channel does not work well.
Solution:   Use a larger buffer and handle overlaps. (Yasuhiro Matsumoto,
            closes #3782)

src/channel.c
src/os_win32.c
src/version.c

index 8f0577f9b62ec6d36155a3ee5a1b81936ff5d959..f6ffcd67d2a1b32066c439d2a5dbb484abc3634a 100644 (file)
@@ -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;
+    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 @@ channel_wait(channel_T *channel, sock_T fd, int timeout)
            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
index 919e07163074b806bed3b9686d387bc20d905bdf..e8c4916a8595a72653c510e3d9328831cf73aab0 100644 (file)
@@ -5428,6 +5428,49 @@ win32_build_env(dict_T *env, garray_T *gap, int is_terminal)
 # endif
 }
 
+/*
+ * Create a pair of pipes.
+ * Return TRUE for success, FALSE for failure.
+ */
+    static BOOL
+create_pipe_pair(HANDLE handles[2])
+{
+    static LONG                s;
+    char               name[64];
+    SECURITY_ATTRIBUTES sa;
+
+    sprintf(name, "\\\\?\\pipe\\vim-%08lx-%08lx",
+           GetCurrentProcessId(),
+           InterlockedIncrement(&s));
+
+    // Create named pipe. Max size of named pipe is 65535.
+    handles[1] = CreateNamedPipe(
+           name,
+           PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
+           PIPE_TYPE_BYTE | PIPE_NOWAIT,
+           1, 65535, 0, 0, NULL);
+
+    if (handles[1] == INVALID_HANDLE_VALUE)
+       return FALSE;
+
+    sa.nLength = sizeof(sa);
+    sa.bInheritHandle = TRUE;
+    sa.lpSecurityDescriptor = NULL;
+
+    handles[0] = CreateFile(name,
+           FILE_GENERIC_READ,
+           FILE_SHARE_READ, &sa,
+           OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+
+    if (handles[0] == INVALID_HANDLE_VALUE)
+    {
+        CloseHandle(handles[1]);
+       return FALSE;
+    }
+
+    return TRUE;
+}
+
     void
 mch_job_start(char *cmd, job_T *job, jobopt_T *options)
 {
@@ -5493,9 +5536,9 @@ mch_job_start(char *cmd, job_T *job, jobopt_T *options)
            goto failed;
        }
     }
-    else if (!use_null_for_in &&
-           (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
-           || !SetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)))
+    else if (!use_null_for_in
+           && (!create_pipe_pair(ifd)
+               || !SetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)))
        goto failed;
 
     if (use_file_for_out)
index da4b2b6f35fd5b8c83c867e09f8fedf7f3e6e737..a83bad6e1d531212948966e187fe01e51117ce33 100644 (file)
@@ -791,6 +791,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    777,
 /**/
     776,
 /**/