Skip to content

Commit e74e8e7

Browse files
committed
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.
1 parent 910b8aa commit e74e8e7

File tree

4 files changed

+58
-18
lines changed

4 files changed

+58
-18
lines changed

src/channel.c

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ add_channel(void)
253253
return NULL;
254254

255255
channel->ch_id = next_ch_id++;
256-
ch_log(channel, "Opening channel\n");
256+
ch_log(channel, "Created channel\n");
257257

258258
#ifdef CHANNEL_PIPES
259259
for (which = CHAN_SOCK; which <= CHAN_IN; ++which)
@@ -458,8 +458,12 @@ channel_gui_unregister(channel_T *channel)
458458

459459
#endif
460460

461+
static char *e_cannot_connect = N_("E902: Cannot connect to port");
462+
461463
/*
462464
* Open a socket channel to "hostname":"port".
465+
* "waittime" is the time in msec to wait for the connection.
466+
* When negative wait forever.
463467
* Returns the channel for success.
464468
* Returns NULL for failure.
465469
*/
@@ -492,7 +496,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
492496

493497
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
494498
{
495-
ch_error(NULL, "in socket() in channel_open().\n");
499+
ch_error(channel, "in socket() in channel_open().\n");
496500
PERROR("E898: socket() in channel_open()");
497501
channel_free(channel);
498502
return NULL;
@@ -505,7 +509,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
505509
server.sin_port = htons(port);
506510
if ((host = gethostbyname(hostname)) == NULL)
507511
{
508-
ch_error(NULL, "in gethostbyname() in channel_open()\n");
512+
ch_error(channel, "in gethostbyname() in channel_open()\n");
509513
PERROR("E901: gethostbyname() in channel_open()");
510514
sock_close(sd);
511515
channel_free(channel);
@@ -525,7 +529,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
525529
)
526530
{
527531
SOCK_ERRNO;
528-
ch_errorn(NULL, "channel_open: Connect failed with errno %d\n",
532+
ch_errorn(channel, "channel_open: Connect failed with errno %d\n",
529533
errno);
530534
sock_close(sd);
531535
channel_free(channel);
@@ -534,7 +538,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
534538
}
535539

536540
/* Try connecting to the server. */
537-
ch_logsn(NULL, "Connecting to %s port %d", hostname, port);
541+
ch_logsn(channel, "Connecting to %s port %d\n", hostname, port);
538542
ret = connect(sd, (struct sockaddr *)&server, sizeof(server));
539543
SOCK_ERRNO;
540544
if (ret < 0)
@@ -545,9 +549,9 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
545549
#endif
546550
)
547551
{
548-
ch_errorn(NULL, "channel_open: Connect failed with errno %d\n",
552+
ch_errorn(channel, "channel_open: Connect failed with errno %d\n",
549553
errno);
550-
PERROR(_("E902: Cannot connect to port"));
554+
PERROR(_(e_cannot_connect));
551555
sock_close(sd);
552556
channel_free(channel);
553557
return NULL;
@@ -558,29 +562,62 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
558562
{
559563
struct timeval tv;
560564
fd_set wfds;
561-
565+
#if defined(__APPLE__) && __APPLE__ == 1
566+
# define PASS_RFDS
567+
fd_set rfds;
568+
569+
FD_ZERO(&rfds);
570+
FD_SET(sd, &rfds);
571+
/* On Mac a zero timeout almost never works. At least wait one
572+
* millisecond. */
573+
if (waittime == 0)
574+
waittime = 1;
575+
#endif
562576
FD_ZERO(&wfds);
563577
FD_SET(sd, &wfds);
564578
tv.tv_sec = waittime / 1000;
565579
tv.tv_usec = (waittime % 1000) * 1000;
566-
ret = select((int)sd + 1, NULL, &wfds, NULL, &tv);
580+
581+
ch_logn(channel, "Waiting for connection (timeout %d msec)...\n",
582+
waittime);
583+
ret = select((int)sd + 1,
584+
#ifdef PASS_RFDS
585+
&rfds,
586+
#else
587+
NULL,
588+
#endif
589+
&wfds, NULL, &tv);
590+
567591
if (ret < 0)
568592
{
569593
SOCK_ERRNO;
570-
ch_errorn(NULL, "channel_open: Connect failed with errno %d\n",
594+
ch_errorn(channel, "channel_open: Connect failed with errno %d\n",
571595
errno);
572-
PERROR(_("E902: Cannot connect to port"));
596+
PERROR(_(e_cannot_connect));
573597
sock_close(sd);
574598
channel_free(channel);
575599
return NULL;
576600
}
601+
#ifdef PASS_RFDS
602+
if (ret == 0 && FD_ISSET(sd, &rfds) && FD_ISSET(sd, &wfds))
603+
{
604+
/* For OS X, this implies error. See tcp(4). */
605+
ch_error(channel, "channel_open: Connect failed\n");
606+
EMSG(_(e_cannot_connect));
607+
sock_close(sd);
608+
channel_free(channel);
609+
return NULL;
610+
}
611+
#endif
577612
if (!FD_ISSET(sd, &wfds))
578613
{
579614
/* don't give an error, we just timed out. */
615+
ch_error(channel, "Connection timed out\n");
580616
sock_close(sd);
581617
channel_free(channel);
582618
return NULL;
583619
}
620+
ch_log(channel, "Connection made\n");
584621
}
585622

586623
if (waittime >= 0)
@@ -600,7 +637,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
600637
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
601638
{
602639
SOCK_ERRNO;
603-
ch_log(NULL, "socket() retry in channel_open()\n");
640+
ch_log(channel, "socket() retry in channel_open()\n");
604641
PERROR("E900: socket() retry in channel_open()");
605642
channel_free(channel);
606643
return NULL;
@@ -614,7 +651,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
614651
while (retries-- && ((errno == ECONNREFUSED)
615652
|| (errno == EINTR)))
616653
{
617-
ch_log(NULL, "retrying...\n");
654+
ch_log(channel, "retrying...\n");
618655
mch_delay(3000L, TRUE);
619656
ui_breakcheck();
620657
if (got_int)
@@ -633,7 +670,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
633670
if (!success)
634671
{
635672
/* Get here when the server can't be found. */
636-
ch_error(NULL, "Cannot connect to port after retry\n");
673+
ch_error(channel, "Cannot connect to port after retry\n");
637674
PERROR(_("E899: Cannot connect to port after retry"));
638675
sock_close(sd);
639676
channel_free(channel);
@@ -1434,7 +1471,7 @@ channel_wait(channel_T *channel, sock_T fd, int timeout)
14341471
int ret;
14351472

14361473
if (timeout > 0)
1437-
ch_logn(channel, "Waiting for %d msec\n", timeout);
1474+
ch_logn(channel, "Waiting for up to %d msec\n", timeout);
14381475

14391476

14401477
# ifdef WIN32
@@ -1447,7 +1484,8 @@ channel_wait(channel_T *channel, sock_T fd, int timeout)
14471484
/* reading from a pipe, not a socket */
14481485
while (TRUE)
14491486
{
1450-
if (PeekNamedPipe((HANDLE)fd, NULL, 0, NULL, &nread, NULL) && nread > 0)
1487+
if (PeekNamedPipe((HANDLE)fd, NULL, 0, NULL, &nread, NULL)
1488+
&& nread > 0)
14511489
return OK;
14521490
diff = deadline - GetTickCount();
14531491
if (diff < 0)

src/eval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10031,7 +10031,7 @@ f_ch_open(typval_T *argvars, typval_T *rettv)
1003110031
if ((item = dict_find(dict, (char_u *)"timeout", -1)) != NULL)
1003210032
timeout = get_tv_number(&item->di_tv);
1003310033
}
10034-
if (waittime < 0 || timeout < 0)
10034+
if (timeout < 0)
1003510035
{
1003610036
EMSG(_(e_invarg));
1003710037
return;

src/testdir/test_channel.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ else
2828
finish
2929
endif
3030

31-
let s:chopt = has('osx') ? {'waittime' : 1} : {}
31+
let s:chopt = {}
3232

3333
" Run "testfunc" after sarting the server and stop the server afterwards.
3434
func s:run_server(testfunc)

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,8 @@ static char *(features[]) =
747747

748748
static int included_patches[] =
749749
{ /* Add new patch number below this line */
750+
/**/
751+
1342,
750752
/**/
751753
1341,
752754
/**/

0 commit comments

Comments
 (0)