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

Changed connect with timeout to use poll() instead if socket() to avoid...

Changed connect with timeout to use poll() instead if socket() to avoid problems with many open files
parent 28e96d95
...@@ -40,14 +40,17 @@ ...@@ -40,14 +40,17 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#ifdef HAVE_SELECT_H #ifdef HAVE_SELECT_H
# include <select.h> #include <select.h>
#endif #endif
#ifdef HAVE_SYS_SELECT_H #ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> #include <sys/select.h>
#endif #endif
#ifdef HAVE_POLL
#include <sys/poll.h>
#endif #endif
#endif /* !defined(MSDOS) && !defined(__WIN__) */
#ifdef HAVE_SYS_UN_H #ifdef HAVE_SYS_UN_H
# include <sys/un.h> #include <sys/un.h>
#endif #endif
#if defined(THREAD) && !defined(__WIN__) #if defined(THREAD) && !defined(__WIN__)
#include <my_pthread.h> /* because of signal() */ #include <my_pthread.h> /* because of signal() */
...@@ -148,9 +151,12 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host, ...@@ -148,9 +151,12 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host,
const char* user, const char* user,
const char* passwd); const char* passwd);
#if !(defined(__WIN__) || defined(OS2) || defined(__NETWARE__))
static int wait_for_data(my_socket fd, uint timeout);
#endif
/**************************************************************************** /****************************************************************************
A modified version of connect(). connect2() allows you to specify A modified version of connect(). my_connect() allows you to specify
a timeout value, in seconds, that we should wait until we a timeout value, in seconds, that we should wait until we
derermine we can't connect to a particular host. If timeout is 0, derermine we can't connect to a particular host. If timeout is 0,
my_connect() will behave exactly like connect(). my_connect() will behave exactly like connect().
...@@ -158,17 +164,13 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host, ...@@ -158,17 +164,13 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host,
Base version coded by Steve Bernacki, Jr. <steve@navinet.net> Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
*****************************************************************************/ *****************************************************************************/
int my_connect(my_socket s, const struct sockaddr *name, uint namelen, int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
uint timeout) uint timeout)
{ {
#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__) #if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
return connect(s, (struct sockaddr*) name, namelen); return connect(fd, (struct sockaddr*) name, namelen);
#else #else
int flags, res, s_err; int flags, res, s_err;
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
fd_set sfds;
struct timeval tv;
time_t start_time, now_time;
/* /*
If they passed us a timeout of zero, we should behave If they passed us a timeout of zero, we should behave
...@@ -176,30 +178,68 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen, ...@@ -176,30 +178,68 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
*/ */
if (timeout == 0) if (timeout == 0)
return connect(s, (struct sockaddr*) name, namelen); return connect(fd, (struct sockaddr*) name, namelen);
flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */ flags = fcntl(fd, F_GETFL, 0); /* Set socket to not block */
#ifdef O_NONBLOCK #ifdef O_NONBLOCK
fcntl(s, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */ fcntl(fd, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */
#endif #endif
res = connect(s, (struct sockaddr*) name, namelen); res= connect(fd, (struct sockaddr*) name, namelen);
s_err = errno; /* Save the error... */ s_err= errno; /* Save the error... */
fcntl(s, F_SETFL, flags); fcntl(fd, F_SETFL, flags);
if ((res != 0) && (s_err != EINPROGRESS)) if ((res != 0) && (s_err != EINPROGRESS))
{ {
errno = s_err; /* Restore it */ errno= s_err; /* Restore it */
return(-1); return(-1);
} }
if (res == 0) /* Connected quickly! */ if (res == 0) /* Connected quickly! */
return(0); return(0);
return wait_for_data(fd, timeout);
#endif
}
/*
Wait up to timeout seconds for a connection to be established.
We prefer to do this with poll() as there is no limitations with this.
If not, we will use select()
*/
#if !(defined(__WIN__) || defined(OS2) || defined(__NETWARE__))
static int wait_for_data(my_socket fd, uint timeout)
{
#ifdef HAVE_POLL
struct pollfd ufds;
int res;
ufds.fd= fd;
ufds.events= POLLIN | POLLPRI;
if (!(res= poll(&ufds, 1, (int) timeout*1000)))
{
errno= EINTR;
return -1;
}
if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
return -1;
return 0;
#else
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
fd_set sfds;
struct timeval tv;
time_t start_time, now_time;
int res, s_err;
if (fd >= FD_SETSIZE) /* Check if wrong error */
return 0; /* Can't use timeout */
/* /*
Otherwise, our connection is "in progress." We can use Our connection is "in progress." We can use the select() call to wait
the select() call to wait up to a specified period of time up to a specified period of time for the connection to suceed.
for the connection to suceed. If select() returns 0 If select() returns 0 (after waiting howevermany seconds), our socket
(after waiting howevermany seconds), our socket never became never became writable (host is probably unreachable.) Otherwise, if
writable (host is probably unreachable.) Otherwise, if
select() returns 1, then one of two conditions exist: select() returns 1, then one of two conditions exist:
1. An error occured. We use getsockopt() to check for this. 1. An error occured. We use getsockopt() to check for this.
...@@ -212,7 +252,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen, ...@@ -212,7 +252,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
*/ */
FD_ZERO(&sfds); FD_ZERO(&sfds);
FD_SET(s, &sfds); FD_SET(fd, &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
...@@ -226,10 +266,10 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen, ...@@ -226,10 +266,10 @@ int my_connect(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(HPUX10) && defined(THREAD) #if defined(HPUX10) && defined(THREAD)
if ((res = select(s+1, NULL, (int*) &sfds, NULL, &tv)) > 0) if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
break; break;
#else #else
if ((res = select(s+1, NULL, &sfds, NULL, &tv)) > 0) if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
break; break;
#endif #endif
if (res == 0) /* timeout */ if (res == 0) /* timeout */
...@@ -247,7 +287,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen, ...@@ -247,7 +287,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
*/ */
s_err=0; s_err=0;
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
return(-1); return(-1);
if (s_err) if (s_err)
...@@ -256,9 +296,9 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen, ...@@ -256,9 +296,9 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
return(-1); /* but return an error... */ return(-1); /* but return an error... */
} }
return (0); /* ok */ return (0); /* ok */
#endif /* HAVE_POLL */
#endif
} }
#endif /* defined(__WIN__) || defined(OS2) || defined(__NETWARE__) */
/* /*
Create a named pipe connection Create a named pipe connection
......
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