0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

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.
This commit is contained in:
Bram Moolenaar
2016-02-16 22:01:30 +01:00
parent 910b8aac5d
commit e74e8e7d75
4 changed files with 57 additions and 17 deletions

View File

@@ -253,7 +253,7 @@ add_channel(void)
return NULL; return NULL;
channel->ch_id = next_ch_id++; channel->ch_id = next_ch_id++;
ch_log(channel, "Opening channel\n"); ch_log(channel, "Created channel\n");
#ifdef CHANNEL_PIPES #ifdef CHANNEL_PIPES
for (which = CHAN_SOCK; which <= CHAN_IN; ++which) for (which = CHAN_SOCK; which <= CHAN_IN; ++which)
@@ -458,8 +458,12 @@ channel_gui_unregister(channel_T *channel)
#endif #endif
static char *e_cannot_connect = N_("E902: Cannot connect to port");
/* /*
* Open a socket channel to "hostname":"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 the channel for success.
* Returns NULL for failure. * Returns NULL for failure.
*/ */
@@ -492,7 +496,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 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()"); PERROR("E898: socket() in channel_open()");
channel_free(channel); channel_free(channel);
return NULL; return NULL;
@@ -505,7 +509,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
server.sin_port = htons(port); server.sin_port = htons(port);
if ((host = gethostbyname(hostname)) == NULL) 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()"); PERROR("E901: gethostbyname() in channel_open()");
sock_close(sd); sock_close(sd);
channel_free(channel); channel_free(channel);
@@ -525,7 +529,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
) )
{ {
SOCK_ERRNO; 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); errno);
sock_close(sd); sock_close(sd);
channel_free(channel); channel_free(channel);
@@ -534,7 +538,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
} }
/* Try connecting to the server. */ /* 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)); ret = connect(sd, (struct sockaddr *)&server, sizeof(server));
SOCK_ERRNO; SOCK_ERRNO;
if (ret < 0) if (ret < 0)
@@ -545,9 +549,9 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
#endif #endif
) )
{ {
ch_errorn(NULL, "channel_open: Connect failed with errno %d\n", ch_errorn(channel, "channel_open: Connect failed with errno %d\n",
errno); errno);
PERROR(_("E902: Cannot connect to port")); PERROR(_(e_cannot_connect));
sock_close(sd); sock_close(sd);
channel_free(channel); channel_free(channel);
return NULL; return NULL;
@@ -558,29 +562,62 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
{ {
struct timeval tv; struct timeval tv;
fd_set wfds; 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_ZERO(&wfds);
FD_SET(sd, &wfds); FD_SET(sd, &wfds);
tv.tv_sec = waittime / 1000; tv.tv_sec = waittime / 1000;
tv.tv_usec = (waittime % 1000) * 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) if (ret < 0)
{ {
SOCK_ERRNO; 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); errno);
PERROR(_("E902: Cannot connect to port")); PERROR(_(e_cannot_connect));
sock_close(sd); sock_close(sd);
channel_free(channel); channel_free(channel);
return NULL; return NULL;
} }
#ifdef PASS_RFDS
if (ret == 0 && FD_ISSET(sd, &rfds) && FD_ISSET(sd, &wfds))
{
/* 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)) if (!FD_ISSET(sd, &wfds))
{ {
/* don't give an error, we just timed out. */ /* don't give an error, we just timed out. */
ch_error(channel, "Connection timed out\n");
sock_close(sd); sock_close(sd);
channel_free(channel); channel_free(channel);
return NULL; return NULL;
} }
ch_log(channel, "Connection made\n");
} }
if (waittime >= 0) if (waittime >= 0)
@@ -600,7 +637,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{ {
SOCK_ERRNO; 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()"); PERROR("E900: socket() retry in channel_open()");
channel_free(channel); channel_free(channel);
return NULL; return NULL;
@@ -614,7 +651,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
while (retries-- && ((errno == ECONNREFUSED) while (retries-- && ((errno == ECONNREFUSED)
|| (errno == EINTR))) || (errno == EINTR)))
{ {
ch_log(NULL, "retrying...\n"); ch_log(channel, "retrying...\n");
mch_delay(3000L, TRUE); mch_delay(3000L, TRUE);
ui_breakcheck(); ui_breakcheck();
if (got_int) if (got_int)
@@ -633,7 +670,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
if (!success) if (!success)
{ {
/* Get here when the server can't be found. */ /* 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")); PERROR(_("E899: Cannot connect to port after retry"));
sock_close(sd); sock_close(sd);
channel_free(channel); channel_free(channel);
@@ -1434,7 +1471,7 @@ channel_wait(channel_T *channel, sock_T fd, int timeout)
int ret; int ret;
if (timeout > 0) 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 # ifdef WIN32
@@ -1447,7 +1484,8 @@ channel_wait(channel_T *channel, sock_T fd, int timeout)
/* reading from a pipe, not a socket */ /* reading from a pipe, not a socket */
while (TRUE) 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; return OK;
diff = deadline - GetTickCount(); diff = deadline - GetTickCount();
if (diff < 0) if (diff < 0)

View File

@@ -10031,7 +10031,7 @@ f_ch_open(typval_T *argvars, typval_T *rettv)
if ((item = dict_find(dict, (char_u *)"timeout", -1)) != NULL) if ((item = dict_find(dict, (char_u *)"timeout", -1)) != NULL)
timeout = get_tv_number(&item->di_tv); timeout = get_tv_number(&item->di_tv);
} }
if (waittime < 0 || timeout < 0) if (timeout < 0)
{ {
EMSG(_(e_invarg)); EMSG(_(e_invarg));
return; return;

View File

@@ -28,7 +28,7 @@ else
finish finish
endif endif
let s:chopt = has('osx') ? {'waittime' : 1} : {} let s:chopt = {}
" Run "testfunc" after sarting the server and stop the server afterwards. " Run "testfunc" after sarting the server and stop the server afterwards.
func s:run_server(testfunc) func s:run_server(testfunc)

View File

@@ -747,6 +747,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 */
/**/
1342,
/**/ /**/
1341, 1341,
/**/ /**/