comparison src/channel.c @ 8096:882ba5080c5c v7.4.1342

commit https://github.com/vim/vim/commit/e74e8e7d758e9312165a931f176185f07a64231a Author: Bram Moolenaar <Bram@vim.org> 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.
author Christian Brabandt <cb@256bit.org>
date Tue, 16 Feb 2016 22:15:04 +0100
parents 18a3f0f05244
children 4aea0b0aa714
comparison
equal deleted inserted replaced
8095:f73de5f10aa2 8096:882ba5080c5c
251 251
252 if (channel == NULL) 252 if (channel == NULL)
253 return NULL; 253 return NULL;
254 254
255 channel->ch_id = next_ch_id++; 255 channel->ch_id = next_ch_id++;
256 ch_log(channel, "Opening channel\n"); 256 ch_log(channel, "Created channel\n");
257 257
258 #ifdef CHANNEL_PIPES 258 #ifdef CHANNEL_PIPES
259 for (which = CHAN_SOCK; which <= CHAN_IN; ++which) 259 for (which = CHAN_SOCK; which <= CHAN_IN; ++which)
260 #else 260 #else
261 which = CHAN_SOCK; 261 which = CHAN_SOCK;
456 } 456 }
457 } 457 }
458 458
459 #endif 459 #endif
460 460
461 static char *e_cannot_connect = N_("E902: Cannot connect to port");
462
461 /* 463 /*
462 * Open a socket channel to "hostname":"port". 464 * Open a socket channel to "hostname":"port".
465 * "waittime" is the time in msec to wait for the connection.
466 * When negative wait forever.
463 * Returns the channel for success. 467 * Returns the channel for success.
464 * Returns NULL for failure. 468 * Returns NULL for failure.
465 */ 469 */
466 channel_T * 470 channel_T *
467 channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void)) 471 channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
490 return NULL; 494 return NULL;
491 } 495 }
492 496
493 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 497 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
494 { 498 {
495 ch_error(NULL, "in socket() in channel_open().\n"); 499 ch_error(channel, "in socket() in channel_open().\n");
496 PERROR("E898: socket() in channel_open()"); 500 PERROR("E898: socket() in channel_open()");
497 channel_free(channel); 501 channel_free(channel);
498 return NULL; 502 return NULL;
499 } 503 }
500 504
503 vim_memset((char *)&server, 0, sizeof(server)); 507 vim_memset((char *)&server, 0, sizeof(server));
504 server.sin_family = AF_INET; 508 server.sin_family = AF_INET;
505 server.sin_port = htons(port); 509 server.sin_port = htons(port);
506 if ((host = gethostbyname(hostname)) == NULL) 510 if ((host = gethostbyname(hostname)) == NULL)
507 { 511 {
508 ch_error(NULL, "in gethostbyname() in channel_open()\n"); 512 ch_error(channel, "in gethostbyname() in channel_open()\n");
509 PERROR("E901: gethostbyname() in channel_open()"); 513 PERROR("E901: gethostbyname() in channel_open()");
510 sock_close(sd); 514 sock_close(sd);
511 channel_free(channel); 515 channel_free(channel);
512 return NULL; 516 return NULL;
513 } 517 }
523 fcntl(sd, F_SETFL, O_NONBLOCK) < 0 527 fcntl(sd, F_SETFL, O_NONBLOCK) < 0
524 #endif 528 #endif
525 ) 529 )
526 { 530 {
527 SOCK_ERRNO; 531 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",
529 errno); 533 errno);
530 sock_close(sd); 534 sock_close(sd);
531 channel_free(channel); 535 channel_free(channel);
532 return NULL; 536 return NULL;
533 } 537 }
534 } 538 }
535 539
536 /* Try connecting to the server. */ 540 /* 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);
538 ret = connect(sd, (struct sockaddr *)&server, sizeof(server)); 542 ret = connect(sd, (struct sockaddr *)&server, sizeof(server));
539 SOCK_ERRNO; 543 SOCK_ERRNO;
540 if (ret < 0) 544 if (ret < 0)
541 { 545 {
542 if (errno != EWOULDBLOCK 546 if (errno != EWOULDBLOCK
543 #ifdef EINPROGRESS 547 #ifdef EINPROGRESS
544 && errno != EINPROGRESS 548 && errno != EINPROGRESS
545 #endif 549 #endif
546 ) 550 )
547 { 551 {
548 ch_errorn(NULL, "channel_open: Connect failed with errno %d\n", 552 ch_errorn(channel, "channel_open: Connect failed with errno %d\n",
549 errno); 553 errno);
550 PERROR(_("E902: Cannot connect to port")); 554 PERROR(_(e_cannot_connect));
551 sock_close(sd); 555 sock_close(sd);
552 channel_free(channel); 556 channel_free(channel);
553 return NULL; 557 return NULL;
554 } 558 }
555 } 559 }
556 560
557 if (waittime >= 0 && ret < 0) 561 if (waittime >= 0 && ret < 0)
558 { 562 {
559 struct timeval tv; 563 struct timeval tv;
560 fd_set wfds; 564 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
562 FD_ZERO(&wfds); 576 FD_ZERO(&wfds);
563 FD_SET(sd, &wfds); 577 FD_SET(sd, &wfds);
564 tv.tv_sec = waittime / 1000; 578 tv.tv_sec = waittime / 1000;
565 tv.tv_usec = (waittime % 1000) * 1000; 579 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
567 if (ret < 0) 591 if (ret < 0)
568 { 592 {
569 SOCK_ERRNO; 593 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",
571 errno); 595 errno);
572 PERROR(_("E902: Cannot connect to port")); 596 PERROR(_(e_cannot_connect));
573 sock_close(sd); 597 sock_close(sd);
574 channel_free(channel); 598 channel_free(channel);
575 return NULL; 599 return NULL;
576 } 600 }
577 if (!FD_ISSET(sd, &wfds)) 601 #ifdef PASS_RFDS
578 { 602 if (ret == 0 && FD_ISSET(sd, &rfds) && FD_ISSET(sd, &wfds))
579 /* don't give an error, we just timed out. */ 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));
580 sock_close(sd); 607 sock_close(sd);
581 channel_free(channel); 608 channel_free(channel);
582 return NULL; 609 return NULL;
583 } 610 }
611 #endif
612 if (!FD_ISSET(sd, &wfds))
613 {
614 /* don't give an error, we just timed out. */
615 ch_error(channel, "Connection timed out\n");
616 sock_close(sd);
617 channel_free(channel);
618 return NULL;
619 }
620 ch_log(channel, "Connection made\n");
584 } 621 }
585 622
586 if (waittime >= 0) 623 if (waittime >= 0)
587 { 624 {
588 #ifdef _WIN32 625 #ifdef _WIN32
598 { 635 {
599 sock_close(sd); 636 sock_close(sd);
600 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 637 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
601 { 638 {
602 SOCK_ERRNO; 639 SOCK_ERRNO;
603 ch_log(NULL, "socket() retry in channel_open()\n"); 640 ch_log(channel, "socket() retry in channel_open()\n");
604 PERROR("E900: socket() retry in channel_open()"); 641 PERROR("E900: socket() retry in channel_open()");
605 channel_free(channel); 642 channel_free(channel);
606 return NULL; 643 return NULL;
607 } 644 }
608 if (connect(sd, (struct sockaddr *)&server, sizeof(server))) 645 if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
612 649
613 SOCK_ERRNO; 650 SOCK_ERRNO;
614 while (retries-- && ((errno == ECONNREFUSED) 651 while (retries-- && ((errno == ECONNREFUSED)
615 || (errno == EINTR))) 652 || (errno == EINTR)))
616 { 653 {
617 ch_log(NULL, "retrying...\n"); 654 ch_log(channel, "retrying...\n");
618 mch_delay(3000L, TRUE); 655 mch_delay(3000L, TRUE);
619 ui_breakcheck(); 656 ui_breakcheck();
620 if (got_int) 657 if (got_int)
621 { 658 {
622 errno = EINTR; 659 errno = EINTR;
631 SOCK_ERRNO; 668 SOCK_ERRNO;
632 } 669 }
633 if (!success) 670 if (!success)
634 { 671 {
635 /* Get here when the server can't be found. */ 672 /* 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");
637 PERROR(_("E899: Cannot connect to port after retry")); 674 PERROR(_("E899: Cannot connect to port after retry"));
638 sock_close(sd); 675 sock_close(sd);
639 channel_free(channel); 676 channel_free(channel);
640 return NULL; 677 return NULL;
641 } 678 }
1432 struct timeval tval; 1469 struct timeval tval;
1433 fd_set rfds; 1470 fd_set rfds;
1434 int ret; 1471 int ret;
1435 1472
1436 if (timeout > 0) 1473 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);
1438 1475
1439 1476
1440 # ifdef WIN32 1477 # ifdef WIN32
1441 if (channel->CH_SOCK == CHAN_FD_INVALID) 1478 if (channel->CH_SOCK == CHAN_FD_INVALID)
1442 { 1479 {
1445 DWORD deadline = GetTickCount() + timeout; 1482 DWORD deadline = GetTickCount() + timeout;
1446 1483
1447 /* reading from a pipe, not a socket */ 1484 /* reading from a pipe, not a socket */
1448 while (TRUE) 1485 while (TRUE)
1449 { 1486 {
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)
1451 return OK; 1489 return OK;
1452 diff = deadline - GetTickCount(); 1490 diff = deadline - GetTickCount();
1453 if (diff < 0) 1491 if (diff < 0)
1454 break; 1492 break;
1455 /* Wait for 5 msec. 1493 /* Wait for 5 msec.