comparison src/channel.c @ 8473:ade1797aa6f4 v7.4.1527

commit https://github.com/vim/vim/commit/562ca7142845273bca656aa5aeeda90f001062e0 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Mar 9 21:50:05 2016 +0100 patch 7.4.1527 Problem: Channel test is flaky on MS-Windows. Solution: Limit the select() timeout to 50 msec and try with a new socket if it fails.
author Christian Brabandt <cb@256bit.org>
date Wed, 09 Mar 2016 22:00:05 +0100
parents 86a327403fb0
children c08c6d19db4d
comparison
equal deleted inserted replaced
8472:d45ad00fd8d2 8473:ade1797aa6f4
626 * For Unix we need to call connect() again after connect() failed. 626 * For Unix we need to call connect() again after connect() failed.
627 * On Win32 one time is sufficient. 627 * On Win32 one time is sufficient.
628 */ 628 */
629 while (TRUE) 629 while (TRUE)
630 { 630 {
631 #ifndef WIN32 631 long elapsed_msec = 0;
632 long elapsed_msec = 0; 632 int waitnow;
633 #endif
634 633
635 if (sd >= 0) 634 if (sd >= 0)
636 sock_close(sd); 635 sock_close(sd);
637 sd = socket(AF_INET, SOCK_STREAM, 0); 636 sd = socket(AF_INET, SOCK_STREAM, 0);
638 if (sd == -1) 637 if (sd == -1)
686 channel_free(channel); 685 channel_free(channel);
687 return NULL; 686 return NULL;
688 } 687 }
689 688
690 /* If connect() didn't finish then try using select() to wait for the 689 /* If connect() didn't finish then try using select() to wait for the
691 * connection to be made. */ 690 * connection to be made. For Win32 always use select() to wait. */
692 #ifndef WIN32 691 #ifndef WIN32
693 if (errno != ECONNREFUSED) 692 if (errno != ECONNREFUSED)
694 #endif 693 #endif
695 { 694 {
696 struct timeval tv; 695 struct timeval tv;
700 int so_error = 0; 699 int so_error = 0;
701 socklen_t so_error_len = sizeof(so_error); 700 socklen_t so_error_len = sizeof(so_error);
702 struct timeval start_tv; 701 struct timeval start_tv;
703 struct timeval end_tv; 702 struct timeval end_tv;
704 #endif 703 #endif
704 /* Limit the waittime to 50 msec. If it doesn't work within this
705 * time we close the socket and try creating it again. */
706 waitnow = waittime > 50 ? 50 : waittime;
705 707
706 FD_ZERO(&rfds); 708 FD_ZERO(&rfds);
707 FD_SET(sd, &rfds); 709 FD_SET(sd, &rfds);
708 FD_ZERO(&wfds); 710 FD_ZERO(&wfds);
709 FD_SET(sd, &wfds); 711 FD_SET(sd, &wfds);
710 712
711 tv.tv_sec = waittime / 1000; 713 tv.tv_sec = waitnow / 1000;
712 tv.tv_usec = (waittime % 1000) * 1000; 714 tv.tv_usec = (waitnow % 1000) * 1000;
713 #ifndef WIN32 715 #ifndef WIN32
714 gettimeofday(&start_tv, NULL); 716 gettimeofday(&start_tv, NULL);
715 #endif 717 #endif
716 ch_logn(channel, 718 ch_logn(channel,
717 "Waiting for connection (waittime %d msec)...", waittime); 719 "Waiting for connection (waiting %d msec)...", waitnow);
718 ret = select((int)sd + 1, &rfds, &wfds, NULL, &tv); 720 ret = select((int)sd + 1, &rfds, &wfds, NULL, &tv);
719 721
720 if (ret < 0) 722 if (ret < 0)
721 { 723 {
722 SOCK_ERRNO; 724 SOCK_ERRNO;
727 channel_free(channel); 729 channel_free(channel);
728 return NULL; 730 return NULL;
729 } 731 }
730 732
731 #ifdef WIN32 733 #ifdef WIN32
732 /* On Win32: select() is expected to work and wait for up to the 734 /* On Win32: select() is expected to work and wait for up to
733 * waittime for the socket to be open. */ 735 * "waitnow" msec for the socket to be open. */
734 if (FD_ISSET(sd, &wfds)) 736 if (FD_ISSET(sd, &wfds))
735 break; 737 break;
738 elapsed_msec = waitnow;
739 if (waittime > 1 && elapsed_msec < waittime)
740 {
741 waittime -= elapsed_msec;
742 continue;
743 }
736 #else 744 #else
737 /* On Linux-like systems: See socket(7) for the behavior 745 /* On Linux-like systems: See socket(7) for the behavior
738 * After putting the socket in non-blocking mode, connect() will 746 * After putting the socket in non-blocking mode, connect() will
739 * return EINPROGRESS, select() will not wait (as if writing is 747 * return EINPROGRESS, select() will not wait (as if writing is
740 * possible), need to use getsockopt() to check if the socket is 748 * possible), need to use getsockopt() to check if the socket is
776 #ifndef WIN32 784 #ifndef WIN32
777 if (waittime > 1 && elapsed_msec < waittime) 785 if (waittime > 1 && elapsed_msec < waittime)
778 { 786 {
779 /* The port isn't ready but we also didn't get an error. 787 /* The port isn't ready but we also didn't get an error.
780 * This happens when the server didn't open the socket 788 * This happens when the server didn't open the socket
781 * yet. Wait a bit and try again. */ 789 * yet. Select() may return early, wait until the remaining
782 mch_delay(waittime < 50 ? (long)waittime : 50L, TRUE); 790 * "waitnow" and try again. */
783 ui_breakcheck(); 791 waitnow -= elapsed_msec;
792 waittime -= elapsed_msec;
793 if (waitnow > 0)
794 {
795 mch_delay((long)waitnow, TRUE);
796 ui_breakcheck();
797 waittime -= waitnow;
798 }
784 if (!got_int) 799 if (!got_int)
785 { 800 {
786 /* reduce the waittime by the elapsed time and the 50 801 if (waittime <= 0)
787 * msec delay (or a bit more) */ 802 /* give it one more try */
788 waittime -= elapsed_msec;
789 if (waittime > 50)
790 waittime -= 50;
791 else
792 waittime = 1; 803 waittime = 1;
793 continue; 804 continue;
794 } 805 }
795 /* we were interrupted, behave as if timed out */ 806 /* we were interrupted, behave as if timed out */
796 } 807 }