0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

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)
This commit is contained in:
Bram Moolenaar 2019-01-19 14:37:00 +01:00
parent b2e54b0092
commit b091f30bf3
3 changed files with 65 additions and 31 deletions

View 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

View 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)

View File

@ -791,6 +791,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
777,
/**/
776,
/**/