# HG changeset patch # User Christian Brabandt # Date 1455912905 -3600 # Node ID 39532ee7dd433ee692c774bc4f1cc1ce7fe71f83 # Parent a479e369498544a7129947191c24f9d3f1d97b8c commit https://github.com/vim/vim/commit/ed5a78e11c80c7b13b233149fd4273b71fc96262 Author: Bram Moolenaar Date: Fri Feb 19 21:05:03 2016 +0100 patch 7.4.1355 Problem: Win32 console and GUI handle channels differently. Solution: Consolidate code between Win32 console and GUI. diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -1508,17 +1508,11 @@ channel_free_all(void) static int channel_wait(channel_T *channel, sock_T fd, int timeout) { -#if defined(HAVE_SELECT) && !defined(FEAT_GUI_W32) - struct timeval tval; - fd_set rfds; - int ret; - if (timeout > 0) ch_logn(channel, "Waiting for up to %d msec", timeout); - # ifdef WIN32 - if (channel->CH_SOCK == CHAN_FD_INVALID) + if (fd != channel->CH_SOCK) { DWORD nread; int diff; @@ -1537,44 +1531,48 @@ channel_wait(channel_T *channel, sock_T * TODO: increase the sleep time when looping more often */ Sleep(5); } - return FAIL; } + 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) + struct timeval tval; + fd_set rfds; + int ret; - FD_ZERO(&rfds); - FD_SET((int)fd, &rfds); - tval.tv_sec = timeout / 1000; - tval.tv_usec = (timeout % 1000) * 1000; - for (;;) - { - ret = select((int)fd + 1, &rfds, NULL, NULL, &tval); -# ifdef EINTR - if (ret == -1 && errno == EINTR) - continue; -# endif - if (ret <= 0) + FD_ZERO(&rfds); + FD_SET((int)fd, &rfds); + tval.tv_sec = timeout / 1000; + tval.tv_usec = (timeout % 1000) * 1000; + for (;;) { - ch_log(channel, "Nothing to read"); - return FAIL; + ret = select((int)fd + 1, &rfds, NULL, NULL, &tval); +# ifdef EINTR + SOCK_ERRNO; + if (ret == -1 && errno == EINTR) + continue; +# endif + if (ret > 0) + return OK; + break; } - break; - } -#else -# ifdef HAVE_POLL - struct pollfd fds; +# else + struct pollfd fds; - if (timeout > 0) - ch_logn(channel, "Waiting for %d msec", timeout); - fds.fd = fd; - fds.events = POLLIN; - if (poll(&fds, 1, timeout) <= 0) - { - ch_log(channel, "Nothing to read"); - return FAIL; - } + fds.fd = fd; + fds.events = POLLIN; + if (poll(&fds, 1, timeout) > 0) + return OK; # endif #endif - return OK; + } + ch_log(channel, "Nothing to read"); + return FAIL; } /* @@ -1667,8 +1665,9 @@ channel_read(channel_T *channel, int whi } #endif - /* Reading a socket disconnection (readlen == 0), or a socket error. */ - if (readlen <= 0) + /* Reading a socket disconnection (readlen == 0), or a socket error. + * TODO: call error callback. */ + if (readlen <= 0 && channel->ch_job == NULL) { /* Queue a "DETACH" netbeans message in the command queue in order to * terminate the netbeans session later. Do not end the session here @@ -1836,6 +1835,35 @@ channel_fd2channel(sock_T fd, int *which } return NULL; } + + void +channel_handle_events(void) +{ + channel_T *channel; + int which; + static int loop = 0; + + /* Skip heavily polling */ + if (loop++ % 2) + return; + + for (channel = first_channel; channel != NULL; channel = channel->ch_next) + { +# ifdef FEAT_GUI_W32 + /* only check the pipes */ + for (which = CHAN_OUT; which < CHAN_ERR; ++which) +# else +# ifdef CHANNEL_PIPES + /* check the socket and pipes */ + for (which = CHAN_SOCK; which < CHAN_ERR; ++which) +# else + /* only check the socket */ + which = CHAN_SOCK; +# endif +# endif + channel_read(channel, which, "channel_handle_events"); + } +} # endif /* @@ -1969,7 +1997,7 @@ channel_poll_check(int ret_in, void *fds } # endif /* UNIX && !HAVE_SELECT */ -# if (!defined(FEAT_GUI_W32) && defined(HAVE_SELECT)) || defined(PROTO) +# if (!defined(WIN32) && defined(HAVE_SELECT)) || defined(PROTO) /* * The type of "rfds" is hidden to avoid problems with the function proto. */ @@ -2034,7 +2062,7 @@ channel_select_check(int ret_in, void *r return ret; } -# endif /* !FEAT_GUI_W32 && HAVE_SELECT */ +# endif /* !WIN32 && HAVE_SELECT */ /* * Execute queued up commands. diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -14635,14 +14635,14 @@ f_job_start(typval_T *argvars UNUSED, ty ga_concat(&ga, (char_u *)" "); ga_concat(&ga, (char_u *)argv[i]); } - ch_logs(NULL, "Starting job: %s", ga.ga_data); + ch_logs(NULL, "Starting job: %s", (char *)ga.ga_data); ga_clear(&ga); } # endif mch_start_job(argv, job, &options); #else # ifdef FEAT_CHANNEL - ch_logs(NULL, "Starting job: %s", cmd); + ch_logs(NULL, "Starting job: %s", (char *)cmd); # endif mch_start_job((char *)cmd, job, &options); #endif diff --git a/src/gui_w48.c b/src/gui_w48.c --- a/src/gui_w48.c +++ b/src/gui_w48.c @@ -2099,6 +2099,10 @@ gui_mch_wait_for_chars(int wtime) parse_queued_messages(); #endif +#ifdef FEAT_CHANNEL + channel_handle_events(); +#endif + /* * Don't use gui_mch_update() because then we will spin-lock until a * char arrives, instead we use GetMessage() to hang until an diff --git a/src/os_win32.c b/src/os_win32.c --- a/src/os_win32.c +++ b/src/os_win32.c @@ -1128,30 +1128,6 @@ mch_setmouse(int on) SetConsoleMode(g_hConIn, cmodein); } -#ifdef FEAT_CHANNEL - static int -handle_channel_event(void) -{ - int ret; - fd_set rfds; - int maxfd; - - FD_ZERO(&rfds); - maxfd = channel_select_setup(-1, &rfds); - if (maxfd >= 0) - { - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = 0; - ret = select(maxfd + 1, &rfds, NULL, NULL, &tv); - if (ret > 0 && channel_select_check(ret, &rfds) > 0) - return TRUE; - } - return FALSE; -} -#endif - /* * Decode a MOUSE_EVENT. If it's a valid event, return MOUSE_LEFT, * MOUSE_MIDDLE, or MOUSE_RIGHT for a click; MOUSE_DRAG for a mouse @@ -1495,8 +1471,7 @@ WaitForChar(long msec) #endif #ifdef FEAT_CHANNEL - if (handle_channel_event()) - return TRUE; + channel_handle_events(); #endif if (0 diff --git a/src/proto/channel.pro b/src/proto/channel.pro --- a/src/proto/channel.pro +++ b/src/proto/channel.pro @@ -30,6 +30,7 @@ void channel_read(channel_T *channel, in char_u *channel_read_block(channel_T *channel); int channel_read_json_block(channel_T *channel, int id, typval_T **rettv); channel_T *channel_fd2channel(sock_T fd, int *whichp); +void channel_handle_events(void); int channel_send(channel_T *channel, char_u *buf, char *fun); int channel_poll_setup(int nfd_in, void *fds_in); int channel_poll_check(int ret_in, void *fds_in); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1355, +/**/ 1354, /**/ 1353,