Mercurial > vim
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; |