diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-01-19 14:37:00 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-01-19 14:37:00 +0100 |
commit | b091f30bf38eacb31b9d8c97c82c7e0af9866301 (patch) | |
tree | 6bd242d9cad2c17b0ff2144666518faf4bae18b0 | |
parent | b2e54b009279754e420c992a5e4ec05b0728d915 (diff) | |
download | vim-git-b091f30bf38eacb31b9d8c97c82c7e0af9866301.tar.gz |
patch 8.1.0777: Win32: using pipes for channel does not work wellv8.1.0777
Problem: Win32: using pipes for channel does not work well.
Solution: Use a larger buffer and handle overlaps. (Yasuhiro Matsumoto,
closes #3782)
-rw-r--r-- | src/channel.c | 45 | ||||
-rw-r--r-- | src/os_win32.c | 49 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 65 insertions, 31 deletions
diff --git a/src/channel.c b/src/channel.c index 8f0577f9b..f6ffcd67d 100644 --- 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; + 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 diff --git a/src/os_win32.c b/src/os_win32.c index 919e07163..e8c4916a8 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -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) diff --git a/src/version.c b/src/version.c index da4b2b6f3..a83bad6e1 100644 --- a/src/version.c +++ b/src/version.c @@ -792,6 +792,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 777, +/**/ 776, /**/ 775, |