Skip to content

Commit d911971

Browse files
committed
MDEV-9041 connect-timeout has no effect on Windows
Replaced my_connect() with cross-plattform, timeout aware vio_socket_connect() function
1 parent 245bfc5 commit d911971

File tree

1 file changed

+4
-185
lines changed

1 file changed

+4
-185
lines changed

sql-common/client.c

Lines changed: 4 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -170,188 +170,6 @@ static int get_vio_connect_timeout(MYSQL *mysql)
170170
}
171171

172172

173-
/****************************************************************************
174-
A modified version of connect(). my_connect() allows you to specify
175-
a timeout value, in seconds, that we should wait until we
176-
derermine we can't connect to a particular host. If timeout is 0,
177-
my_connect() will behave exactly like connect().
178-
179-
Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
180-
*****************************************************************************/
181-
182-
int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
183-
uint timeout)
184-
{
185-
#if defined(__WIN__)
186-
DBUG_ENTER("my_connect");
187-
DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen));
188-
#else
189-
int flags, res, s_err;
190-
DBUG_ENTER("my_connect");
191-
DBUG_PRINT("enter", ("fd: %d timeout: %u", fd, timeout));
192-
193-
/*
194-
If they passed us a timeout of zero, we should behave
195-
exactly like the normal connect() call does.
196-
*/
197-
198-
if (timeout == 0)
199-
DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen));
200-
201-
flags = fcntl(fd, F_GETFL, 0); /* Set socket to not block */
202-
#ifdef O_NONBLOCK
203-
fcntl(fd, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */
204-
#endif
205-
206-
DBUG_PRINT("info", ("connecting non-blocking"));
207-
res= connect(fd, (struct sockaddr*) name, namelen);
208-
DBUG_PRINT("info", ("connect result: %d errno: %d", res, errno));
209-
s_err= errno; /* Save the error... */
210-
fcntl(fd, F_SETFL, flags);
211-
if ((res != 0) && (s_err != EINPROGRESS))
212-
{
213-
errno= s_err; /* Restore it */
214-
DBUG_RETURN(-1);
215-
}
216-
if (res == 0) /* Connected quickly! */
217-
DBUG_RETURN(0);
218-
DBUG_RETURN(wait_for_data(fd, timeout));
219-
#endif
220-
}
221-
222-
223-
/*
224-
Wait up to timeout seconds for a connection to be established.
225-
226-
We prefer to do this with poll() as there is no limitations with this.
227-
If not, we will use select()
228-
*/
229-
230-
#if !defined(__WIN__)
231-
232-
static int wait_for_data(my_socket fd, uint timeout)
233-
{
234-
#ifdef HAVE_POLL
235-
struct pollfd ufds;
236-
int res;
237-
DBUG_ENTER("wait_for_data");
238-
239-
DBUG_PRINT("info", ("polling"));
240-
ufds.fd= fd;
241-
ufds.events= POLLIN | POLLPRI;
242-
if (!(res= poll(&ufds, 1, (int) timeout*1000)))
243-
{
244-
DBUG_PRINT("info", ("poll timed out"));
245-
errno= EINTR;
246-
DBUG_RETURN(-1);
247-
}
248-
DBUG_PRINT("info",
249-
("poll result: %d errno: %d revents: 0x%02d events: 0x%02d",
250-
res, errno, ufds.revents, ufds.events));
251-
if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
252-
DBUG_RETURN(-1);
253-
/*
254-
At this point, we know that something happened on the socket.
255-
But this does not means that everything is alright.
256-
The connect might have failed. We need to retrieve the error code
257-
from the socket layer. We must return success only if we are sure
258-
that it was really a success. Otherwise we might prevent the caller
259-
from trying another address to connect to.
260-
*/
261-
{
262-
int s_err;
263-
socklen_t s_len= sizeof(s_err);
264-
265-
DBUG_PRINT("info", ("Get SO_ERROR from non-blocked connected socket."));
266-
res= getsockopt(fd, SOL_SOCKET, SO_ERROR, &s_err, &s_len);
267-
DBUG_PRINT("info", ("getsockopt res: %d s_err: %d", res, s_err));
268-
if (res)
269-
DBUG_RETURN(res);
270-
/* getsockopt() was successful, check the retrieved status value. */
271-
if (s_err)
272-
{
273-
errno= s_err;
274-
DBUG_RETURN(-1);
275-
}
276-
/* Status from connect() is zero. Socket is successfully connected. */
277-
}
278-
DBUG_RETURN(0);
279-
#else
280-
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
281-
fd_set sfds;
282-
struct timeval tv;
283-
time_t start_time, now_time;
284-
int res, s_err;
285-
DBUG_ENTER("wait_for_data");
286-
287-
if (fd >= FD_SETSIZE) /* Check if wrong error */
288-
DBUG_RETURN(0); /* Can't use timeout */
289-
290-
/*
291-
Our connection is "in progress." We can use the select() call to wait
292-
up to a specified period of time for the connection to suceed.
293-
If select() returns 0 (after waiting howevermany seconds), our socket
294-
never became writable (host is probably unreachable.) Otherwise, if
295-
select() returns 1, then one of two conditions exist:
296-
297-
1. An error occured. We use getsockopt() to check for this.
298-
2. The connection was set up sucessfully: getsockopt() will
299-
return 0 as an error.
300-
301-
Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
302-
who posted this method of timing out a connect() in
303-
comp.unix.programmer on August 15th, 1997.
304-
*/
305-
306-
FD_ZERO(&sfds);
307-
FD_SET(fd, &sfds);
308-
/*
309-
select could be interrupted by a signal, and if it is,
310-
the timeout should be adjusted and the select restarted
311-
to work around OSes that don't restart select and
312-
implementations of select that don't adjust tv upon
313-
failure to reflect the time remaining
314-
*/
315-
start_time= my_time(0);
316-
for (;;)
317-
{
318-
tv.tv_sec = (long) timeout;
319-
tv.tv_usec = 0;
320-
#if defined(HPUX10)
321-
if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
322-
break;
323-
#else
324-
if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
325-
break;
326-
#endif
327-
if (res == 0) /* timeout */
328-
DBUG_RETURN(-1);
329-
now_time= my_time(0);
330-
timeout-= (uint) (now_time - start_time);
331-
if (errno != EINTR || (int) timeout <= 0)
332-
DBUG_RETURN(-1);
333-
}
334-
335-
/*
336-
select() returned something more interesting than zero, let's
337-
see if we have any errors. If the next two statements pass,
338-
we've got an open socket!
339-
*/
340-
341-
s_err=0;
342-
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
343-
DBUG_RETURN(-1);
344-
345-
if (s_err)
346-
{ /* getsockopt could succeed */
347-
errno = s_err;
348-
DBUG_RETURN(-1); /* but return an error... */
349-
}
350-
DBUG_RETURN(0); /* ok */
351-
#endif /* HAVE_POLL */
352-
}
353-
#endif /* !defined(__WIN__) */
354-
355173
/**
356174
Set the internal error message to mysql handler
357175
@@ -3165,19 +2983,20 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
31652983

31662984
static int
31672985
connect_sync_or_async(MYSQL *mysql, NET *net, my_socket fd,
3168-
const struct sockaddr *name, uint namelen)
2986+
struct sockaddr *name, uint namelen)
31692987
{
2988+
int vio_timeout = get_vio_connect_timeout(mysql);
2989+
31702990
if (mysql->options.extension && mysql->options.extension->async_context &&
31712991
mysql->options.extension->async_context->active)
31722992
{
31732993
my_bool old_mode;
3174-
int vio_timeout= get_vio_connect_timeout(mysql);
31752994
vio_blocking(net->vio, FALSE, &old_mode);
31762995
return my_connect_async(mysql->options.extension->async_context, fd,
31772996
name, namelen, vio_timeout);
31782997
}
31792998

3180-
return my_connect(fd, name, namelen, mysql->options.connect_timeout);
2999+
return vio_socket_connect(net->vio, name, namelen, vio_timeout);
31813000
}
31823001

31833002

0 commit comments

Comments
 (0)