Commit 11016134 authored by monty@narttu.mysql.fi's avatar monty@narttu.mysql.fi

Better fix for connect timeout problem.

parent 9277579c
...@@ -121,15 +121,16 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen, ...@@ -121,15 +121,16 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen,
#if defined(__WIN__) || defined(OS2) #if defined(__WIN__) || defined(OS2)
return connect(s, (struct sockaddr*) name, namelen); return connect(s, (struct sockaddr*) name, namelen);
#else #else
int flags, res, s_err, result=0; int flags, res, s_err;
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint); SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
fd_set sfds; fd_set sfds;
struct timeval tv; struct timeval tv;
time_t start_time, now_time; time_t start_time, now_time;
/* If they passed us a timeout of zero, we should behave /*
* exactly like the normal connect() call does. If they passed us a timeout of zero, we should behave
*/ exactly like the normal connect() call does.
*/
if (timeout == 0) if (timeout == 0)
return connect(s, (struct sockaddr*) name, namelen); return connect(s, (struct sockaddr*) name, namelen);
...@@ -150,30 +151,31 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen, ...@@ -150,30 +151,31 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen,
if (res == 0) /* Connected quickly! */ if (res == 0) /* Connected quickly! */
return(0); return(0);
/* Otherwise, our connection is "in progress." We can use /*
* the select() call to wait up to a specified period of time Otherwise, our connection is "in progress." We can use
* for the connection to suceed. If select() returns 0 the select() call to wait up to a specified period of time
* (after waiting howevermany seconds), our socket never became for the connection to suceed. If select() returns 0
* writable (host is probably unreachable.) Otherwise, if (after waiting howevermany seconds), our socket never became
* select() returns 1, then one of two conditions exist: writable (host is probably unreachable.) Otherwise, if
* select() returns 1, then one of two conditions exist:
* 1. An error occured. We use getsockopt() to check for this.
* 2. The connection was set up sucessfully: getsockopt() will 1. An error occured. We use getsockopt() to check for this.
* return 0 as an error. 2. The connection was set up sucessfully: getsockopt() will
* return 0 as an error.
* Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
* who posted this method of timing out a connect() in Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
* comp.unix.programmer on August 15th, 1997. who posted this method of timing out a connect() in
*/ comp.unix.programmer on August 15th, 1997.
*/
FD_ZERO(&sfds); FD_ZERO(&sfds);
FD_SET(s, &sfds); FD_SET(s, &sfds);
/* /*
* select could be interrupted by a signal, and if it is, select could be interrupted by a signal, and if it is,
* the timeout should be adjusted and the select restarted the timeout should be adjusted and the select restarted
* to work around OSes that don't restart select and to work around OSes that don't restart select and
* implementations of select that don't adjust tv upon implementations of select that don't adjust tv upon
* failure to reflect the time remaining failure to reflect the time remaining
*/ */
start_time = time(NULL); start_time = time(NULL);
for (;;) for (;;)
...@@ -181,22 +183,25 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen, ...@@ -181,22 +183,25 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen,
tv.tv_sec = (long) timeout; tv.tv_sec = (long) timeout;
tv.tv_usec = 0; tv.tv_usec = 0;
#if defined(HPUX) && defined(THREAD) #if defined(HPUX) && defined(THREAD)
if ((result = select(s+1, NULL, (int*) &sfds, NULL, &tv)) >= 0) if ((res = select(s+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
break; break;
#else #else
if ((result = select(s+1, NULL, &sfds, NULL, &tv)) >= 0) if ((res = select(s+1, NULL, &sfds, NULL, &tv)) > 0)
break; break;
#endif #endif
if (res == 0) /* timeout */
return -1;
now_time=time(NULL); now_time=time(NULL);
timeout-= (uint) (now_time - start_time); timeout-= (uint) (now_time - start_time);
if (errno != EINTR || (int) timeout <= 0) if (errno != EINTR || (int) timeout <= 0)
return -1; return -1;
} }
/* select() returned something more interesting than zero, let's /*
* see if we have any errors. If the next two statements pass, select() returned something more interesting than zero, let's
* we've got an open socket! see if we have any errors. If the next two statements pass,
*/ we've got an open socket!
*/
s_err=0; s_err=0;
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
...@@ -207,10 +212,8 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen, ...@@ -207,10 +212,8 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen,
errno = s_err; errno = s_err;
return(-1); /* but return an error... */ return(-1); /* but return an error... */
} }
if (res && result > 0) return (0); /* ok */
result=res=0; // We did it in select() !!!
return((res) ? res : result); /* It's all good! */
#endif #endif
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment