comparison src/channel.c @ 8467:86a327403fb0 v7.4.1524

commit https://github.com/vim/vim/commit/045a284a83c2a85113de233d5233eae34724a4b6 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Mar 8 22:33:07 2016 +0100 patch 7.4.1524 Problem: Channel test fails on BSD. Solution: Break out of the loop when connect() succeeds. (Ozaki Kiichi)
author Christian Brabandt <cb@256bit.org>
date Tue, 08 Mar 2016 22:45:04 +0100
parents 508504ca52ac
children ade1797aa6f4
comparison
equal deleted inserted replaced
8466:e9e6914bef63 8467:86a327403fb0
585 #ifdef WIN32 585 #ifdef WIN32
586 u_short port = port_in; 586 u_short port = port_in;
587 u_long val = 1; 587 u_long val = 1;
588 #else 588 #else
589 int port = port_in; 589 int port = port_in;
590 struct timeval start_tv;
591 #endif 590 #endif
592 channel_T *channel; 591 channel_T *channel;
593 int ret; 592 int ret;
594 593
595 #ifdef WIN32 594 #ifdef WIN32
627 * For Unix we need to call connect() again after connect() failed. 626 * For Unix we need to call connect() again after connect() failed.
628 * On Win32 one time is sufficient. 627 * On Win32 one time is sufficient.
629 */ 628 */
630 while (TRUE) 629 while (TRUE)
631 { 630 {
631 #ifndef WIN32
632 long elapsed_msec = 0;
633 #endif
634
632 if (sd >= 0) 635 if (sd >= 0)
633 sock_close(sd); 636 sock_close(sd);
634 sd = socket(AF_INET, SOCK_STREAM, 0); 637 sd = socket(AF_INET, SOCK_STREAM, 0);
635 if (sd == -1) 638 if (sd == -1)
636 { 639 {
662 665
663 /* Try connecting to the server. */ 666 /* Try connecting to the server. */
664 ch_logsn(channel, "Connecting to %s port %d", hostname, port); 667 ch_logsn(channel, "Connecting to %s port %d", hostname, port);
665 ret = connect(sd, (struct sockaddr *)&server, sizeof(server)); 668 ret = connect(sd, (struct sockaddr *)&server, sizeof(server));
666 669
670 if (ret == 0)
671 /* The connection could be established. */
672 break;
673
667 SOCK_ERRNO; 674 SOCK_ERRNO;
668 if (ret < 0) 675 if (waittime < 0 || (errno != EWOULDBLOCK
669 { 676 && errno != ECONNREFUSED
670 if (errno != EWOULDBLOCK
671 && errno != ECONNREFUSED
672 #ifdef EINPROGRESS 677 #ifdef EINPROGRESS
673 && errno != EINPROGRESS 678 && errno != EINPROGRESS
674 #endif 679 #endif
675 ) 680 ))
676 { 681 {
677 ch_errorn(channel, 682 ch_errorn(channel,
678 "channel_open: Connect failed with errno %d", errno); 683 "channel_open: Connect failed with errno %d", errno);
679 PERROR(_(e_cannot_connect)); 684 PERROR(_(e_cannot_connect));
680 sock_close(sd); 685 sock_close(sd);
681 channel_free(channel); 686 channel_free(channel);
682 return NULL; 687 return NULL;
683 } 688 }
684 } 689
685 690 /* If connect() didn't finish then try using select() to wait for the
686 /* If we don't block and connect() failed then try using select() to 691 * connection to be made. */
687 * wait for the connection to be made. */ 692 #ifndef WIN32
688 if (waittime >= 0 && ret < 0) 693 if (errno != ECONNREFUSED)
694 #endif
689 { 695 {
690 struct timeval tv; 696 struct timeval tv;
691 fd_set rfds; 697 fd_set rfds;
692 fd_set wfds; 698 fd_set wfds;
693 #ifndef WIN32 699 #ifndef WIN32
694 int so_error = 0; 700 int so_error = 0;
695 socklen_t so_error_len = sizeof(so_error); 701 socklen_t so_error_len = sizeof(so_error);
702 struct timeval start_tv;
703 struct timeval end_tv;
696 #endif 704 #endif
697 705
698 FD_ZERO(&rfds); 706 FD_ZERO(&rfds);
699 FD_SET(sd, &rfds); 707 FD_SET(sd, &rfds);
700 FD_ZERO(&wfds); 708 FD_ZERO(&wfds);
721 } 729 }
722 730
723 #ifdef WIN32 731 #ifdef WIN32
724 /* On Win32: select() is expected to work and wait for up to the 732 /* On Win32: select() is expected to work and wait for up to the
725 * waittime for the socket to be open. */ 733 * waittime for the socket to be open. */
726 if (!FD_ISSET(sd, &wfds) || ret == 0) 734 if (FD_ISSET(sd, &wfds))
735 break;
727 #else 736 #else
728 /* On Linux-like systems: See socket(7) for the behavior 737 /* On Linux-like systems: See socket(7) for the behavior
729 * After putting the socket in non-blocking mode, connect() will 738 * After putting the socket in non-blocking mode, connect() will
730 * return EINPROGRESS, select() will not wait (as if writing is 739 * return EINPROGRESS, select() will not wait (as if writing is
731 * possible), need to use getsockopt() to check if the socket is 740 * possible), need to use getsockopt() to check if the socket is
732 * actually able to connect. 741 * actually able to connect.
733 * We detect an failure to connect when either read and write fds 742 * We detect a failure to connect when either read and write fds
734 * are set. Use getsockopt() to find out what kind of failure. */ 743 * are set. Use getsockopt() to find out what kind of failure. */
735 if (FD_ISSET(sd, &rfds) || FD_ISSET(sd, &wfds)) 744 if (FD_ISSET(sd, &rfds) || FD_ISSET(sd, &wfds))
736 { 745 {
737 ret = getsockopt(sd, 746 ret = getsockopt(sd,
738 SOL_SOCKET, SO_ERROR, &so_error, &so_error_len); 747 SOL_SOCKET, SO_ERROR, &so_error, &so_error_len);
739 if (ret < 0 || (so_error != 0 748 if (ret < 0 || (so_error != 0
740 && so_error != EWOULDBLOCK 749 && so_error != EWOULDBLOCK
741 && so_error != ECONNREFUSED 750 && so_error != ECONNREFUSED
742 # ifdef EINPROGRESS 751 # ifdef EINPROGRESS
743 && so_error != EINPROGRESS 752 && so_error != EINPROGRESS
752 channel_free(channel); 761 channel_free(channel);
753 return NULL; 762 return NULL;
754 } 763 }
755 } 764 }
756 765
757 if (!FD_ISSET(sd, &wfds) || so_error != 0) 766 if (FD_ISSET(sd, &wfds) && so_error == 0)
758 #endif 767 /* Did not detect an error, connection is established. */
768 break;
769
770 gettimeofday(&end_tv, NULL);
771 elapsed_msec = (end_tv.tv_sec - start_tv.tv_sec) * 1000
772 + (end_tv.tv_usec - start_tv.tv_usec) / 1000;
773 #endif
774 }
775
776 #ifndef WIN32
777 if (waittime > 1 && elapsed_msec < waittime)
778 {
779 /* The port isn't ready but we also didn't get an error.
780 * This happens when the server didn't open the socket
781 * yet. Wait a bit and try again. */
782 mch_delay(waittime < 50 ? (long)waittime : 50L, TRUE);
783 ui_breakcheck();
784 if (!got_int)
759 { 785 {
760 #ifndef WIN32 786 /* reduce the waittime by the elapsed time and the 50
761 struct timeval end_tv; 787 * msec delay (or a bit more) */
762 long elapsed_msec; 788 waittime -= elapsed_msec;
763 789 if (waittime > 50)
764 gettimeofday(&end_tv, NULL); 790 waittime -= 50;
765 elapsed_msec = (end_tv.tv_sec - start_tv.tv_sec) * 1000 791 else
766 + (end_tv.tv_usec - start_tv.tv_usec) / 1000; 792 waittime = 1;
767 if (waittime > 1 && elapsed_msec < waittime) 793 continue;
768 {
769 /* The port isn't ready but we also didn't get an error.
770 * This happens when the server didn't open the socket
771 * yet. Wait a bit and try again. */
772 mch_delay(waittime < 50 ? (long)waittime : 50L, TRUE);
773 ui_breakcheck();
774 if (!got_int)
775 {
776 /* reduce the waittime by the elapsed time and the 50
777 * msec delay (or a bit more) */
778 waittime -= elapsed_msec;
779 if (waittime > 50)
780 waittime -= 50;
781 else
782 waittime = 1;
783 continue;
784 }
785 /* we were interrupted, behave as if timed out */
786 }
787 #endif
788 /* We timed out. */
789 ch_error(channel, "Connection timed out");
790 sock_close(sd);
791 channel_free(channel);
792 return NULL;
793 } 794 }
794 795 /* we were interrupted, behave as if timed out */
795 ch_log(channel, "Connection made"); 796 }
796 break; 797 #endif
797 } 798
798 } 799 /* We timed out. */
800 ch_error(channel, "Connection timed out");
801 sock_close(sd);
802 channel_free(channel);
803 return NULL;
804 }
805
806 ch_log(channel, "Connection made");
799 807
800 if (waittime >= 0) 808 if (waittime >= 0)
801 { 809 {
802 #ifdef _WIN32 810 #ifdef _WIN32
803 val = 0; 811 val = 0;