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