changeset 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 e9e6914bef63
children 846d3556abc9
files src/channel.c src/version.c
diffstat 2 files changed, 68 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/src/channel.c
+++ b/src/channel.c
@@ -587,7 +587,6 @@ channel_open(
     u_long		val = 1;
 #else
     int			port = port_in;
-    struct timeval	start_tv;
 #endif
     channel_T		*channel;
     int			ret;
@@ -629,6 +628,10 @@ channel_open(
      */
     while (TRUE)
     {
+#ifndef WIN32
+	long elapsed_msec = 0;
+#endif
+
 	if (sd >= 0)
 	    sock_close(sd);
 	sd = socket(AF_INET, SOCK_STREAM, 0);
@@ -664,28 +667,31 @@ channel_open(
 	ch_logsn(channel, "Connecting to %s port %d", hostname, port);
 	ret = connect(sd, (struct sockaddr *)&server, sizeof(server));
 
+	if (ret == 0)
+	    /* The connection could be established. */
+	    break;
+
 	SOCK_ERRNO;
-	if (ret < 0)
-	{
-	    if (errno != EWOULDBLOCK
-		    && errno != ECONNREFUSED
+	if (waittime < 0 || (errno != EWOULDBLOCK
+		&& errno != ECONNREFUSED
 #ifdef EINPROGRESS
-		    && errno != EINPROGRESS
+		&& errno != EINPROGRESS
 #endif
-		    )
-	    {
-		ch_errorn(channel,
-			"channel_open: Connect failed with errno %d", errno);
-		PERROR(_(e_cannot_connect));
-		sock_close(sd);
-		channel_free(channel);
-		return NULL;
-	    }
+		))
+	{
+	    ch_errorn(channel,
+			 "channel_open: Connect failed with errno %d", errno);
+	    PERROR(_(e_cannot_connect));
+	    sock_close(sd);
+	    channel_free(channel);
+	    return NULL;
 	}
 
-	/* If we don't block and connect() failed then try using select() to
-	 * wait for the connection to be made. */
-	if (waittime >= 0 && ret < 0)
+	/* If connect() didn't finish then try using select() to wait for the
+	 * connection to be made. */
+#ifndef WIN32
+	if (errno != ECONNREFUSED)
+#endif
 	{
 	    struct timeval	tv;
 	    fd_set		rfds;
@@ -693,6 +699,8 @@ channel_open(
 #ifndef WIN32
 	    int			so_error = 0;
 	    socklen_t		so_error_len = sizeof(so_error);
+	    struct timeval	start_tv;
+	    struct timeval	end_tv;
 #endif
 
 	    FD_ZERO(&rfds);
@@ -723,19 +731,20 @@ channel_open(
 #ifdef WIN32
 	    /* On Win32: select() is expected to work and wait for up to the
 	     * waittime for the socket to be open. */
-	    if (!FD_ISSET(sd, &wfds) || ret == 0)
+	    if (FD_ISSET(sd, &wfds))
+		break;
 #else
 	    /* On Linux-like systems: See socket(7) for the behavior
 	     * After putting the socket in non-blocking mode, connect() will
 	     * return EINPROGRESS, select() will not wait (as if writing is
 	     * possible), need to use getsockopt() to check if the socket is
 	     * actually able to connect.
-	     * We detect an failure to connect when either read and write fds
+	     * We detect a failure to connect when either read and write fds
 	     * are set.  Use getsockopt() to find out what kind of failure. */
 	    if (FD_ISSET(sd, &rfds) || FD_ISSET(sd, &wfds))
 	    {
 		ret = getsockopt(sd,
-			    SOL_SOCKET, SO_ERROR, &so_error, &so_error_len);
+			      SOL_SOCKET, SO_ERROR, &so_error, &so_error_len);
 		if (ret < 0 || (so_error != 0
 			&& so_error != EWOULDBLOCK
 			&& so_error != ECONNREFUSED
@@ -754,49 +763,48 @@ channel_open(
 		}
 	    }
 
-	    if (!FD_ISSET(sd, &wfds) || so_error != 0)
+	    if (FD_ISSET(sd, &wfds) && so_error == 0)
+		/* Did not detect an error, connection is established. */
+		break;
+
+	    gettimeofday(&end_tv, NULL);
+	    elapsed_msec = (end_tv.tv_sec - start_tv.tv_sec) * 1000
+			     + (end_tv.tv_usec - start_tv.tv_usec) / 1000;
 #endif
-	    {
-#ifndef WIN32
-		struct  timeval end_tv;
-		long    elapsed_msec;
+	}
 
-		gettimeofday(&end_tv, NULL);
-		elapsed_msec = (end_tv.tv_sec - start_tv.tv_sec) * 1000
-				 + (end_tv.tv_usec - start_tv.tv_usec) / 1000;
-		if (waittime > 1 && elapsed_msec < waittime)
-		{
-		    /* The port isn't ready but we also didn't get an error.
-		     * This happens when the server didn't open the socket
-		     * yet.  Wait a bit and try again. */
-		    mch_delay(waittime < 50 ? (long)waittime : 50L, TRUE);
-		    ui_breakcheck();
-		    if (!got_int)
-		    {
-			/* reduce the waittime by the elapsed time and the 50
-			 * msec delay (or a bit more) */
-			waittime -= elapsed_msec;
-			if (waittime > 50)
-			    waittime -= 50;
-			else
-			    waittime = 1;
-			continue;
-		    }
-		    /* we were interrupted, behave as if timed out */
-		}
+#ifndef WIN32
+	if (waittime > 1 && elapsed_msec < waittime)
+	{
+	    /* The port isn't ready but we also didn't get an error.
+	     * This happens when the server didn't open the socket
+	     * yet.  Wait a bit and try again. */
+	    mch_delay(waittime < 50 ? (long)waittime : 50L, TRUE);
+	    ui_breakcheck();
+	    if (!got_int)
+	    {
+		/* reduce the waittime by the elapsed time and the 50
+		 * msec delay (or a bit more) */
+		waittime -= elapsed_msec;
+		if (waittime > 50)
+		    waittime -= 50;
+		else
+		    waittime = 1;
+		continue;
+	    }
+	    /* we were interrupted, behave as if timed out */
+	}
 #endif
-		/* We timed out. */
-		ch_error(channel, "Connection timed out");
-		sock_close(sd);
-		channel_free(channel);
-		return NULL;
-	    }
 
-	    ch_log(channel, "Connection made");
-	    break;
-	}
+	/* We timed out. */
+	ch_error(channel, "Connection timed out");
+	sock_close(sd);
+	channel_free(channel);
+	return NULL;
     }
 
+    ch_log(channel, "Connection made");
+
     if (waittime >= 0)
     {
 #ifdef _WIN32
--- a/src/version.c
+++ b/src/version.c
@@ -744,6 +744,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1524,
+/**/
     1523,
 /**/
     1522,