summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-01-24 23:11:49 +0100
committerBram Moolenaar <Bram@vim.org>2019-01-24 23:11:49 +0100
commit240583869ae477202494dd01ef1e8e2bac650f10 (patch)
tree11fc0b707bd3d9c5dba5da5f706b413373cf0824
parent99531a7604ce89ba82f41cdb519669abb61f3df0 (diff)
downloadvim-git-240583869ae477202494dd01ef1e8e2bac650f10.tar.gz
patch 8.1.0818: MS-Windows: cannot send large data with ch_sendraw()v8.1.0818
Problem: MS-Windows: cannot send large data with ch_sendraw(). Solution: Split write into several WriteFile() calls. (Yasuhiro Matsumoto, closes #3823)
-rw-r--r--src/channel.c34
-rw-r--r--src/os_win32.c2
-rw-r--r--src/testdir/test_channel.vim18
-rw-r--r--src/testdir/test_channel_pipe.py4
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h4
6 files changed, 51 insertions, 13 deletions
diff --git a/src/channel.c b/src/channel.c
index 3a80748a1..b013a8558 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -80,24 +80,34 @@ fd_read(sock_T fd, char *buf, size_t len)
static int
fd_write(sock_T fd, char *buf, size_t len)
{
+ size_t todo = len;
HANDLE h = (HANDLE)fd;
- DWORD nwrite;
+ DWORD nwrite, size, done = 0;
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))
+ while (todo > 0)
{
- DWORD err = GetLastError();
+ if (todo > MAX_NAMED_PIPE_SIZE)
+ size = MAX_NAMED_PIPE_SIZE;
+ else
+ size = todo;
+ // 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 + done, size, &nwrite, &ov))
+ {
+ DWORD err = GetLastError();
- if (err != ERROR_IO_PENDING)
- return -1;
- if (!GetOverlappedResult(h, &ov, &nwrite, FALSE))
- return -1;
- FlushFileBuffers(h);
+ if (err != ERROR_IO_PENDING)
+ return -1;
+ if (!GetOverlappedResult(h, &ov, &nwrite, FALSE))
+ return -1;
+ FlushFileBuffers(h);
+ }
+ todo -= nwrite;
+ done += nwrite;
}
- return (int)nwrite;
+ return (int)done;
}
static void
diff --git a/src/os_win32.c b/src/os_win32.c
index 8966053b8..6a127a44a 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -5369,7 +5369,7 @@ create_pipe_pair(HANDLE handles[2])
name,
PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_NOWAIT,
- 1, 65535, 0, 0, NULL);
+ 1, MAX_NAMED_PIPE_SIZE, 0, 0, NULL);
if (handles[1] == INVALID_HANDLE_VALUE)
return FALSE;
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index 15ca9ddbb..e7fcf9582 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -1980,3 +1980,21 @@ func Test_job_start_in_timer()
unlet! g:val
unlet! g:job
endfunc
+
+func Test_raw_large_data()
+ try
+ let g:out = ''
+ let job = job_start(s:python . " test_channel_pipe.py",
+ \ {'mode': 'raw', 'drop': 'never', 'noblock': 1,
+ \ 'callback': {ch, msg -> execute('let g:out .= msg')}})
+
+ let want = repeat('X', 79999) . "\n"
+ call ch_sendraw(job, want)
+ let g:Ch_job = job
+ call WaitForAssert({-> assert_equal("dead", job_status(g:Ch_job))})
+ call assert_equal(want, substitute(g:out, '\r', '', 'g'))
+ finally
+ call job_stop(job)
+ unlet g:out
+ endtry
+endfunc
diff --git a/src/testdir/test_channel_pipe.py b/src/testdir/test_channel_pipe.py
index 940378624..810a8e303 100644
--- a/src/testdir/test_channel_pipe.py
+++ b/src/testdir/test_channel_pipe.py
@@ -56,4 +56,8 @@ if __name__ == "__main__":
if typed.startswith("doubleerr "):
print(typed[10:-1] + "\nAND " + typed[10:-1], file=sys.stderr)
sys.stderr.flush()
+ if typed.startswith("XXX"):
+ print(typed, end='')
+ sys.stderr.flush()
+ break
diff --git a/src/version.c b/src/version.c
index 532b449dd..4beae276f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -788,6 +788,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 818,
+/**/
817,
/**/
816,
diff --git a/src/vim.h b/src/vim.h
index 55cb69389..5bd1b3c94 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2467,6 +2467,10 @@ typedef enum {
# define MAX_OPEN_CHANNELS 0
#endif
+#if defined(WIN32)
+# define MAX_NAMED_PIPE_SIZE 65535
+#endif
+
/* Options for json_encode() and json_decode. */
#define JSON_JS 1 /* use JS instead of JSON */
#define JSON_NO_NONE 2 /* v:none item not allowed */