# HG changeset patch # User Christian Brabandt # Date 1455657304 -3600 # Node ID 882ba5080c5ca54fd29801dff13a01fbbea79003 # Parent f73de5f10aa258505bfa174fcfec1fab0d5edecd commit https://github.com/vim/vim/commit/e74e8e7d758e9312165a931f176185f07a64231a Author: Bram Moolenaar Date: Tue Feb 16 22:01:30 2016 +0100 patch 7.4.1342 Problem: On Mac OS/X the waittime must be > 0 for connect to work. Solution: Use select() in a different way. (partly by Kazunobu Kuriyama) Always use a waittime of 1 or more. diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -253,7 +253,7 @@ add_channel(void) return NULL; channel->ch_id = next_ch_id++; - ch_log(channel, "Opening channel\n"); + ch_log(channel, "Created channel\n"); #ifdef CHANNEL_PIPES for (which = CHAN_SOCK; which <= CHAN_IN; ++which) @@ -458,8 +458,12 @@ channel_gui_unregister(channel_T *channe #endif +static char *e_cannot_connect = N_("E902: Cannot connect to port"); + /* * Open a socket channel to "hostname":"port". + * "waittime" is the time in msec to wait for the connection. + * When negative wait forever. * Returns the channel for success. * Returns NULL for failure. */ @@ -492,7 +496,7 @@ channel_open(char *hostname, int port_in if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - ch_error(NULL, "in socket() in channel_open().\n"); + ch_error(channel, "in socket() in channel_open().\n"); PERROR("E898: socket() in channel_open()"); channel_free(channel); return NULL; @@ -505,7 +509,7 @@ channel_open(char *hostname, int port_in server.sin_port = htons(port); if ((host = gethostbyname(hostname)) == NULL) { - ch_error(NULL, "in gethostbyname() in channel_open()\n"); + ch_error(channel, "in gethostbyname() in channel_open()\n"); PERROR("E901: gethostbyname() in channel_open()"); sock_close(sd); channel_free(channel); @@ -525,7 +529,7 @@ channel_open(char *hostname, int port_in ) { SOCK_ERRNO; - ch_errorn(NULL, "channel_open: Connect failed with errno %d\n", + ch_errorn(channel, "channel_open: Connect failed with errno %d\n", errno); sock_close(sd); channel_free(channel); @@ -534,7 +538,7 @@ channel_open(char *hostname, int port_in } /* Try connecting to the server. */ - ch_logsn(NULL, "Connecting to %s port %d", hostname, port); + ch_logsn(channel, "Connecting to %s port %d\n", hostname, port); ret = connect(sd, (struct sockaddr *)&server, sizeof(server)); SOCK_ERRNO; if (ret < 0) @@ -545,9 +549,9 @@ channel_open(char *hostname, int port_in #endif ) { - ch_errorn(NULL, "channel_open: Connect failed with errno %d\n", + ch_errorn(channel, "channel_open: Connect failed with errno %d\n", errno); - PERROR(_("E902: Cannot connect to port")); + PERROR(_(e_cannot_connect)); sock_close(sd); channel_free(channel); return NULL; @@ -558,29 +562,62 @@ channel_open(char *hostname, int port_in { struct timeval tv; fd_set wfds; +#if defined(__APPLE__) && __APPLE__ == 1 +# define PASS_RFDS + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(sd, &rfds); + /* On Mac a zero timeout almost never works. At least wait one + * millisecond. */ + if (waittime == 0) + waittime = 1; +#endif FD_ZERO(&wfds); FD_SET(sd, &wfds); tv.tv_sec = waittime / 1000; tv.tv_usec = (waittime % 1000) * 1000; - ret = select((int)sd + 1, NULL, &wfds, NULL, &tv); + + ch_logn(channel, "Waiting for connection (timeout %d msec)...\n", + waittime); + ret = select((int)sd + 1, +#ifdef PASS_RFDS + &rfds, +#else + NULL, +#endif + &wfds, NULL, &tv); + if (ret < 0) { SOCK_ERRNO; - ch_errorn(NULL, "channel_open: Connect failed with errno %d\n", + ch_errorn(channel, "channel_open: Connect failed with errno %d\n", errno); - PERROR(_("E902: Cannot connect to port")); + PERROR(_(e_cannot_connect)); sock_close(sd); channel_free(channel); return NULL; } - if (!FD_ISSET(sd, &wfds)) +#ifdef PASS_RFDS + if (ret == 0 && FD_ISSET(sd, &rfds) && FD_ISSET(sd, &wfds)) { - /* don't give an error, we just timed out. */ + /* For OS X, this implies error. See tcp(4). */ + ch_error(channel, "channel_open: Connect failed\n"); + EMSG(_(e_cannot_connect)); sock_close(sd); channel_free(channel); return NULL; } +#endif + if (!FD_ISSET(sd, &wfds)) + { + /* don't give an error, we just timed out. */ + ch_error(channel, "Connection timed out\n"); + sock_close(sd); + channel_free(channel); + return NULL; + } + ch_log(channel, "Connection made\n"); } if (waittime >= 0) @@ -600,7 +637,7 @@ channel_open(char *hostname, int port_in if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { SOCK_ERRNO; - ch_log(NULL, "socket() retry in channel_open()\n"); + ch_log(channel, "socket() retry in channel_open()\n"); PERROR("E900: socket() retry in channel_open()"); channel_free(channel); return NULL; @@ -614,7 +651,7 @@ channel_open(char *hostname, int port_in while (retries-- && ((errno == ECONNREFUSED) || (errno == EINTR))) { - ch_log(NULL, "retrying...\n"); + ch_log(channel, "retrying...\n"); mch_delay(3000L, TRUE); ui_breakcheck(); if (got_int) @@ -633,7 +670,7 @@ channel_open(char *hostname, int port_in if (!success) { /* Get here when the server can't be found. */ - ch_error(NULL, "Cannot connect to port after retry\n"); + ch_error(channel, "Cannot connect to port after retry\n"); PERROR(_("E899: Cannot connect to port after retry")); sock_close(sd); channel_free(channel); @@ -1434,7 +1471,7 @@ channel_wait(channel_T *channel, sock_T int ret; if (timeout > 0) - ch_logn(channel, "Waiting for %d msec\n", timeout); + ch_logn(channel, "Waiting for up to %d msec\n", timeout); # ifdef WIN32 @@ -1447,7 +1484,8 @@ channel_wait(channel_T *channel, sock_T /* reading from a pipe, not a socket */ while (TRUE) { - if (PeekNamedPipe((HANDLE)fd, NULL, 0, NULL, &nread, NULL) && nread > 0) + if (PeekNamedPipe((HANDLE)fd, NULL, 0, NULL, &nread, NULL) + && nread > 0) return OK; diff = deadline - GetTickCount(); if (diff < 0) diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -10031,7 +10031,7 @@ f_ch_open(typval_T *argvars, typval_T *r if ((item = dict_find(dict, (char_u *)"timeout", -1)) != NULL) timeout = get_tv_number(&item->di_tv); } - if (waittime < 0 || timeout < 0) + if (timeout < 0) { EMSG(_(e_invarg)); return; 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 @@ -28,7 +28,7 @@ else finish endif -let s:chopt = has('osx') ? {'waittime' : 1} : {} +let s:chopt = {} " Run "testfunc" after sarting the server and stop the server afterwards. func s:run_server(testfunc) 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 */ /**/ + 1342, +/**/ 1341, /**/ 1340,