To: vim_dev@googlegroups.com Subject: Patch 7.4.1342 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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. Files: src/eval.c, src/channel.c, src/testdir/test_channel.vim *** ../vim-7.4.1341/src/eval.c 2016-02-16 21:02:17.603873545 +0100 --- src/eval.c 2016-02-16 21:13:24.020861321 +0100 *************** *** 10031,10037 **** if ((item = dict_find(dict, (char_u *)"timeout", -1)) != NULL) timeout = get_tv_number(&item->di_tv); } ! if (waittime < 0 || timeout < 0) { EMSG(_(e_invarg)); return; --- 10031,10037 ---- if ((item = dict_find(dict, (char_u *)"timeout", -1)) != NULL) timeout = get_tv_number(&item->di_tv); } ! if (timeout < 0) { EMSG(_(e_invarg)); return; *** ../vim-7.4.1341/src/channel.c 2016-02-16 21:02:17.603873545 +0100 --- src/channel.c 2016-02-16 21:55:34.934173321 +0100 *************** *** 253,259 **** return NULL; channel->ch_id = next_ch_id++; ! ch_log(channel, "Opening channel\n"); #ifdef CHANNEL_PIPES for (which = CHAN_SOCK; which <= CHAN_IN; ++which) --- 253,259 ---- return NULL; channel->ch_id = next_ch_id++; ! ch_log(channel, "Created channel\n"); #ifdef CHANNEL_PIPES for (which = CHAN_SOCK; which <= CHAN_IN; ++which) *************** *** 458,465 **** --- 458,469 ---- #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,498 **** if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { ! ch_error(NULL, "in socket() in channel_open().\n"); PERROR("E898: socket() in channel_open()"); channel_free(channel); return NULL; --- 496,502 ---- if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { ! ch_error(channel, "in socket() in channel_open().\n"); PERROR("E898: socket() in channel_open()"); channel_free(channel); return NULL; *************** *** 505,511 **** server.sin_port = htons(port); if ((host = gethostbyname(hostname)) == NULL) { ! ch_error(NULL, "in gethostbyname() in channel_open()\n"); PERROR("E901: gethostbyname() in channel_open()"); sock_close(sd); channel_free(channel); --- 509,515 ---- server.sin_port = htons(port); if ((host = gethostbyname(hostname)) == NULL) { ! ch_error(channel, "in gethostbyname() in channel_open()\n"); PERROR("E901: gethostbyname() in channel_open()"); sock_close(sd); channel_free(channel); *************** *** 525,531 **** ) { SOCK_ERRNO; ! ch_errorn(NULL, "channel_open: Connect failed with errno %d\n", errno); sock_close(sd); channel_free(channel); --- 529,535 ---- ) { SOCK_ERRNO; ! ch_errorn(channel, "channel_open: Connect failed with errno %d\n", errno); sock_close(sd); channel_free(channel); *************** *** 534,540 **** } /* Try connecting to the server. */ ! ch_logsn(NULL, "Connecting to %s port %d", hostname, port); ret = connect(sd, (struct sockaddr *)&server, sizeof(server)); SOCK_ERRNO; if (ret < 0) --- 538,544 ---- } /* Try connecting to the server. */ ! 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,553 **** #endif ) { ! ch_errorn(NULL, "channel_open: Connect failed with errno %d\n", errno); ! PERROR(_("E902: Cannot connect to port")); sock_close(sd); channel_free(channel); return NULL; --- 549,557 ---- #endif ) { ! ch_errorn(channel, "channel_open: Connect failed with errno %d\n", errno); ! PERROR(_(e_cannot_connect)); sock_close(sd); channel_free(channel); return NULL; *************** *** 558,586 **** { struct timeval tv; fd_set wfds; ! 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); if (ret < 0) { SOCK_ERRNO; ! ch_errorn(NULL, "channel_open: Connect failed with errno %d\n", errno); ! PERROR(_("E902: Cannot connect to port")); sock_close(sd); channel_free(channel); return NULL; } if (!FD_ISSET(sd, &wfds)) { /* don't give an error, we just timed out. */ sock_close(sd); channel_free(channel); return NULL; } } if (waittime >= 0) --- 562,623 ---- { 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; ! ! 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(channel, "channel_open: Connect failed with errno %d\n", errno); ! PERROR(_(e_cannot_connect)); sock_close(sd); channel_free(channel); 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)) { /* 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,606 **** if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { SOCK_ERRNO; ! ch_log(NULL, "socket() retry in channel_open()\n"); PERROR("E900: socket() retry in channel_open()"); channel_free(channel); return NULL; --- 637,643 ---- if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { SOCK_ERRNO; ! ch_log(channel, "socket() retry in channel_open()\n"); PERROR("E900: socket() retry in channel_open()"); channel_free(channel); return NULL; *************** *** 614,620 **** while (retries-- && ((errno == ECONNREFUSED) || (errno == EINTR))) { ! ch_log(NULL, "retrying...\n"); mch_delay(3000L, TRUE); ui_breakcheck(); if (got_int) --- 651,657 ---- while (retries-- && ((errno == ECONNREFUSED) || (errno == EINTR))) { ! ch_log(channel, "retrying...\n"); mch_delay(3000L, TRUE); ui_breakcheck(); if (got_int) *************** *** 633,639 **** if (!success) { /* Get here when the server can't be found. */ ! ch_error(NULL, "Cannot connect to port after retry\n"); PERROR(_("E899: Cannot connect to port after retry")); sock_close(sd); channel_free(channel); --- 670,676 ---- if (!success) { /* Get here when the server can't be found. */ ! 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,1440 **** int ret; if (timeout > 0) ! ch_logn(channel, "Waiting for %d msec\n", timeout); # ifdef WIN32 --- 1471,1477 ---- int ret; if (timeout > 0) ! ch_logn(channel, "Waiting for up to %d msec\n", timeout); # ifdef WIN32 *************** *** 1447,1453 **** /* reading from a pipe, not a socket */ while (TRUE) { ! if (PeekNamedPipe((HANDLE)fd, NULL, 0, NULL, &nread, NULL) && nread > 0) return OK; diff = deadline - GetTickCount(); if (diff < 0) --- 1484,1491 ---- /* reading from a pipe, not a socket */ while (TRUE) { ! if (PeekNamedPipe((HANDLE)fd, NULL, 0, NULL, &nread, NULL) ! && nread > 0) return OK; diff = deadline - GetTickCount(); if (diff < 0) *** ../vim-7.4.1341/src/testdir/test_channel.vim 2016-02-16 21:02:17.603873545 +0100 --- src/testdir/test_channel.vim 2016-02-16 21:56:56.329313942 +0100 *************** *** 28,34 **** finish endif ! let s:chopt = has('osx') ? {'waittime' : 1} : {} " Run "testfunc" after sarting the server and stop the server afterwards. func s:run_server(testfunc) --- 28,34 ---- finish endif ! let s:chopt = {} " Run "testfunc" after sarting the server and stop the server afterwards. func s:run_server(testfunc) *** ../vim-7.4.1341/src/version.c 2016-02-16 21:02:17.607873503 +0100 --- src/version.c 2016-02-16 21:57:53.160713954 +0100 *************** *** 749,750 **** --- 749,752 ---- { /* Add new patch number below this line */ + /**/ + 1342, /**/ -- Facepalm statement #7: "Last week I almost got pregnant!" /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///