mirror of
https://github.com/vim/vim.git
synced 2025-10-01 04:54:07 -04:00
patch 8.1.0818: MS-Windows: cannot send large data with ch_sendraw()
Problem: MS-Windows: cannot send large data with ch_sendraw(). Solution: Split write into several WriteFile() calls. (Yasuhiro Matsumoto, closes #3823)
This commit is contained in:
@@ -80,24 +80,34 @@ fd_read(sock_T fd, char *buf, size_t len)
|
|||||||
static int
|
static int
|
||||||
fd_write(sock_T fd, char *buf, size_t len)
|
fd_write(sock_T fd, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
size_t todo = len;
|
||||||
HANDLE h = (HANDLE)fd;
|
HANDLE h = (HANDLE)fd;
|
||||||
DWORD nwrite;
|
DWORD nwrite, size, done = 0;
|
||||||
OVERLAPPED ov;
|
OVERLAPPED ov;
|
||||||
|
|
||||||
// If the pipe overflows while the job does not read the data, WriteFile
|
while (todo > 0)
|
||||||
// will block forever. This abandons the write.
|
|
||||||
memset(&ov, 0, sizeof(ov));
|
|
||||||
if (!WriteFile(h, buf, (DWORD)len, &nwrite, &ov))
|
|
||||||
{
|
{
|
||||||
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)
|
if (err != ERROR_IO_PENDING)
|
||||||
return -1;
|
return -1;
|
||||||
if (!GetOverlappedResult(h, &ov, &nwrite, FALSE))
|
if (!GetOverlappedResult(h, &ov, &nwrite, FALSE))
|
||||||
return -1;
|
return -1;
|
||||||
FlushFileBuffers(h);
|
FlushFileBuffers(h);
|
||||||
|
}
|
||||||
|
todo -= nwrite;
|
||||||
|
done += nwrite;
|
||||||
}
|
}
|
||||||
return (int)nwrite;
|
return (int)done;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -5369,7 +5369,7 @@ create_pipe_pair(HANDLE handles[2])
|
|||||||
name,
|
name,
|
||||||
PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
|
PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
|
||||||
PIPE_TYPE_BYTE | PIPE_NOWAIT,
|
PIPE_TYPE_BYTE | PIPE_NOWAIT,
|
||||||
1, 65535, 0, 0, NULL);
|
1, MAX_NAMED_PIPE_SIZE, 0, 0, NULL);
|
||||||
|
|
||||||
if (handles[1] == INVALID_HANDLE_VALUE)
|
if (handles[1] == INVALID_HANDLE_VALUE)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@@ -1980,3 +1980,21 @@ func Test_job_start_in_timer()
|
|||||||
unlet! g:val
|
unlet! g:val
|
||||||
unlet! g:job
|
unlet! g:job
|
||||||
endfunc
|
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
|
||||||
|
@@ -56,4 +56,8 @@ if __name__ == "__main__":
|
|||||||
if typed.startswith("doubleerr "):
|
if typed.startswith("doubleerr "):
|
||||||
print(typed[10:-1] + "\nAND " + typed[10:-1], file=sys.stderr)
|
print(typed[10:-1] + "\nAND " + typed[10:-1], file=sys.stderr)
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
|
if typed.startswith("XXX"):
|
||||||
|
print(typed, end='')
|
||||||
|
sys.stderr.flush()
|
||||||
|
break
|
||||||
|
|
||||||
|
@@ -787,6 +787,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
818,
|
||||||
/**/
|
/**/
|
||||||
817,
|
817,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -2467,6 +2467,10 @@ typedef enum {
|
|||||||
# define MAX_OPEN_CHANNELS 0
|
# define MAX_OPEN_CHANNELS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
# define MAX_NAMED_PIPE_SIZE 65535
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Options for json_encode() and json_decode. */
|
/* Options for json_encode() and json_decode. */
|
||||||
#define JSON_JS 1 /* use JS instead of JSON */
|
#define JSON_JS 1 /* use JS instead of JSON */
|
||||||
#define JSON_NO_NONE 2 /* v:none item not allowed */
|
#define JSON_NO_NONE 2 /* v:none item not allowed */
|
||||||
|
Reference in New Issue
Block a user