# HG changeset patch # User Christian Brabandt # Date 1456253105 -3600 # Node ID 4f0677020a4395319191c9456e85f2357a93aa0f # Parent 5def36f799a29527bd02d84bf64fef635d90b020 commit https://github.com/vim/vim/commit/9186a276222ea8a7c88f4092ac5b4201381f4e20 Author: Bram Moolenaar Date: Tue Feb 23 19:34:01 2016 +0100 patch 7.4.1404 Problem: ch_read() doesn't time out on MS-Windows. Solution: Instead of WM_NETBEANS use select(). (Yukihiro Nakadaira) diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -52,10 +52,6 @@ # define fd_close(sd) close(sd) #endif -#ifdef FEAT_GUI_W32 -extern HWND s_hwnd; /* Gvim's Window handle */ -#endif - #ifdef WIN32 static int fd_read(sock_T fd, char *buf, size_t len) @@ -296,9 +292,6 @@ add_channel(void) #ifdef FEAT_GUI_GTK channel->ch_part[part].ch_inputHandler = 0; #endif -#ifdef FEAT_GUI_W32 - channel->ch_part[part].ch_inputHandler = -1; -#endif channel->ch_part[part].ch_timeout = 2000; } @@ -421,15 +414,6 @@ channel_gui_register_one(channel_T *chan messageFromNetbeans, (gpointer)(long)channel->ch_part[part].ch_fd); # endif -# else -# ifdef FEAT_GUI_W32 - /* Tell Windows we are interested in receiving message when there - * is input on the editor connection socket. */ - if (channel->ch_part[part].ch_inputHandler == -1) - channel->ch_part[part].ch_inputHandler = WSAAsyncSelect( - channel->ch_part[part].ch_fd, - s_hwnd, WM_NETBEANS, FD_READ); -# endif # endif # endif } @@ -491,14 +475,6 @@ channel_gui_unregister(channel_T *channe # endif channel->ch_part[part].ch_inputHandler = 0; } -# else -# ifdef FEAT_GUI_W32 - if (channel->ch_part[part].ch_inputHandler == 0) - { - WSAAsyncSelect(channel->ch_part[part].ch_fd, s_hwnd, 0, 0); - channel->ch_part[part].ch_inputHandler = -1; - } -# endif # endif # endif } @@ -1630,7 +1606,6 @@ channel_free_all(void) /* * Check for reading from "fd" with "timeout" msec. * Return FAIL when there is nothing to read. - * Always returns OK for FEAT_GUI_W32. */ static int channel_wait(channel_T *channel, sock_T fd, int timeout) @@ -1662,12 +1637,7 @@ channel_wait(channel_T *channel, sock_T else #endif { -#if defined(FEAT_GUI_W32) - /* Can't check socket for Win32 GUI, always return OK. */ - ch_log(channel, "Can't check, assuming there is something to read"); - return OK; -#else -# if defined(HAVE_SELECT) +#if defined(HAVE_SELECT) struct timeval tval; fd_set rfds; int ret; @@ -1679,23 +1649,22 @@ channel_wait(channel_T *channel, sock_T for (;;) { ret = select((int)fd + 1, &rfds, NULL, NULL, &tval); -# ifdef EINTR +# ifdef EINTR SOCK_ERRNO; if (ret == -1 && errno == EINTR) continue; -# endif +# endif if (ret > 0) return OK; break; } -# else +#else struct pollfd fds; fds.fd = fd; fds.events = POLLIN; if (poll(&fds, 1, timeout) > 0) return OK; -# endif #endif } ch_log(channel, "Nothing to read"); @@ -1764,16 +1733,6 @@ channel_read(channel_T *channel, int par if (len < MAXMSGSIZE) break; /* did read everything that's available */ } -#ifdef FEAT_GUI_W32 - if (use_socket && len == SOCKET_ERROR) - { - /* For Win32 GUI channel_wait() always returns OK and we handle the - * situation that there is nothing to read here. - * TODO: how about a timeout? */ - if (WSAGetLastError() == WSAEWOULDBLOCK) - return; - } -#endif /* Reading a disconnection (readlen == 0), or an error. * TODO: call error callback. */ @@ -1970,17 +1929,12 @@ channel_handle_events(void) for (channel = first_channel; channel != NULL; channel = channel->ch_next) { -# ifdef FEAT_GUI_W32 - /* only check the pipes */ - for (part = PART_OUT; part <= PART_ERR; ++part) -# else -# ifdef CHANNEL_PIPES +# ifdef CHANNEL_PIPES /* check the socket and pipes */ for (part = PART_SOCK; part <= PART_ERR; ++part) -# else +# else /* only check the socket */ part = PART_SOCK; -# endif # endif { fd = channel->ch_part[part].ch_fd; diff --git a/src/gui_w32.c b/src/gui_w32.c --- a/src/gui_w32.c +++ b/src/gui_w32.c @@ -1927,24 +1927,6 @@ process_message(void) } #endif -#ifdef FEAT_CHANNEL - if (msg.message == WM_NETBEANS) - { - int part; - channel_T *channel = channel_fd2channel((sock_T)msg.wParam, &part); - - if (channel != NULL) - { - /* Disable error messages, they can mess up the display and throw - * an exception. */ - ++emsg_off; - channel_read(channel, part, "process_message"); - --emsg_off; - } - return; - } -#endif - #ifdef FEAT_SNIFF if (sniff_request_waiting && want_sniff_request) { @@ -2245,7 +2227,18 @@ gui_mch_wait_for_chars(int wtime) } #ifdef MESSAGE_QUEUE - parse_queued_messages(); + /* Check channel while waiting message. */ + for (;;) + { + MSG msg; + + parse_queued_messages(); + + if (pPeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) + || MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLEVENTS) + != WAIT_TIMEOUT) + break; + } #endif /* diff --git a/src/os_win32.c b/src/os_win32.c --- a/src/os_win32.c +++ b/src/os_win32.c @@ -1492,6 +1492,11 @@ WaitForChar(long msec) { DWORD dwWaitTime = dwEndTime - dwNow; +#ifdef FEAT_CHANNEL + /* Check channel while waiting input. */ + if (dwWaitTime > 100) + dwWaitTime = 100; +#endif #ifdef FEAT_MZSCHEME if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || (long)dwWaitTime > p_mzq)) diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1336,9 +1336,6 @@ typedef struct { #ifdef FEAT_GUI_GTK gint ch_inputHandler; /* Cookie for input */ #endif -#ifdef WIN32 - int ch_inputHandler; /* ret.value of WSAAsyncSelect() */ -#endif ch_mode_T ch_mode; int ch_timeout; /* request timeout in msec */ diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -131,10 +131,10 @@ func s:communicate(port) call assert_false(1, 's:responseHandle was not set') else call assert_equal(handle, s:responseHandle) + unlet s:responseHandle endif call assert_equal('got it', s:responseMsg) - unlet s:responseHandle let s:responseMsg = '' call ch_sendexpr(handle, 'hello!', {'callback': function('s:RequestHandler')}) sleep 10m @@ -142,6 +142,7 @@ func s:communicate(port) call assert_false(1, 's:responseHandle was not set') else call assert_equal(handle, s:responseHandle) + unlet s:responseHandle endif call assert_equal('got it', s:responseMsg) @@ -186,15 +187,12 @@ func s:communicate(port) call assert_equal('ok', ch_sendexpr(handle, 'empty-request')) " Reading while there is nothing available. - " TODO: make this work for MS-Windows - if has('unix') - call assert_equal(v:none, ch_read(handle, {'timeout': 0})) - let start = reltime() - call assert_equal(v:none, ch_read(handle, {'timeout': 333})) - let elapsed = reltime(start) - call assert_true(reltimefloat(elapsed) > 0.3) - call assert_true(reltimefloat(elapsed) < 0.6) - endif + call assert_equal(v:none, ch_read(handle, {'timeout': 0})) + let start = reltime() + call assert_equal(v:none, ch_read(handle, {'timeout': 333})) + let elapsed = reltime(start) + call assert_true(reltimefloat(elapsed) > 0.3) + call assert_true(reltimefloat(elapsed) < 0.6) " Send without waiting for a response, then wait for a response. call ch_sendexpr(handle, 'wait a bit', {'callback': 0}) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -749,6 +749,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1404, +/**/ 1403, /**/ 1402, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -1897,10 +1897,6 @@ typedef int sock_T; # ifdef FEAT_OLE # define WM_OLE (WM_APP+0) # endif -# ifdef FEAT_CHANNEL - /* message for channel socket event */ -# define WM_NETBEANS (WM_APP+1) -# endif # endif /* Info about selected text */