0
0
mirror of https://github.com/vim/vim.git synced 2025-10-09 06:14:17 -04:00

patch 8.1.0889: MS-Windows: a channel write may hang

Problem:    MS-Windows: a channel write may hang.
Solution:   Check for WriteFile() not writing anything. (Yasuhiro Matsumoto,
            closes #3920)
This commit is contained in:
Bram Moolenaar
2019-02-10 22:23:26 +01:00
parent 31b816042f
commit 6524068ff3
4 changed files with 26 additions and 2 deletions

View File

@@ -91,9 +91,10 @@ fd_write(sock_T fd, char *buf, size_t len)
size = MAX_NAMED_PIPE_SIZE; size = MAX_NAMED_PIPE_SIZE;
else else
size = (DWORD)todo; size = (DWORD)todo;
// If the pipe overflows while the job does not read the data, WriteFile // If the pipe overflows while the job does not read the data,
// will block forever. This abandons the write. // WriteFile() will block forever. This abandons the write.
memset(&ov, 0, sizeof(ov)); memset(&ov, 0, sizeof(ov));
nwrite = 0;
if (!WriteFile(h, buf + done, size, &nwrite, &ov)) if (!WriteFile(h, buf + done, size, &nwrite, &ov))
{ {
DWORD err = GetLastError(); DWORD err = GetLastError();
@@ -104,6 +105,10 @@ fd_write(sock_T fd, char *buf, size_t len)
return -1; return -1;
FlushFileBuffers(h); FlushFileBuffers(h);
} }
else if (nwrite == 0)
// WriteFile() returns TRUE but did not write anything. This causes
// a hang, so bail out.
break;
todo -= nwrite; todo -= nwrite;
done += nwrite; done += nwrite;
} }

View File

@@ -2003,6 +2003,20 @@ func Test_raw_large_data()
endtry endtry
endfunc endfunc
func Test_no_hang_windows()
if !has('job') || !has('win32')
return
endif
try
let job = job_start(s:python . " test_channel_pipe.py busy",
\ {'mode': 'raw', 'drop': 'never', 'noblock': 0})
call assert_fails('call ch_sendraw(job, repeat("X", 80000))', 'E631:')
finally
call job_stop(job)
endtry
endfunc
func Test_job_exitval_and_termsig() func Test_job_exitval_and_termsig()
if !has('unix') if !has('unix')
return return

View File

@@ -18,6 +18,9 @@ if __name__ == "__main__":
print(sys.argv[1], end='') print(sys.argv[1], end='')
sys.stdout.flush() sys.stdout.flush()
sys.exit(0) sys.exit(0)
elif sys.argv[1].startswith("busy"):
time.sleep(100)
sys.exit(0)
else: else:
print(sys.argv[1]) print(sys.argv[1])
sys.stdout.flush() sys.stdout.flush()

View File

@@ -783,6 +783,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 */
/**/
889,
/**/ /**/
888, 888,
/**/ /**/