summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <kroki/tomash@moonlight.intranet>2006-09-18 22:02:06 +0400
committerunknown <kroki/tomash@moonlight.intranet>2006-09-18 22:02:06 +0400
commit0b2a28f5cf69237f501b075dd3cfde318768fce8 (patch)
tree239a22917b95abda36af68025cb1329170dc0517
parentdcb665900136fb4015589680c612add8abf1deca (diff)
downloadmariadb-git-0b2a28f5cf69237f501b075dd3cfde318768fce8.tar.gz
BUG#9678: Client library hangs after network communication failure
(back-port to 4.0) Socket timeouts in client library were used only on Windows. Additionally, in 4.0 write operations erroneously set read timeout. The solution is to use socket timeouts in client library on all systems were they are supported, and to differentiate between read and write timeouts. No test case is provided because it is impossible to simulate network failure in current test suite. include/violite.h: Add argument to vio_timeout() to determine which timeout should be set: for read (false) or for write (true). libmysqld/lib_vio.c: Add argument to vio_timeout() to determine which timeout should be set: for read (false) or for write (true). sql/net_serv.cc: Add argument to vio_timeout() to determine which timeout should be set: for read (false) or for write (true). vio/viosocket.c: Add argument to vio_timeout() to determine which timeout should be set: for read (false) or for write (true). Implement socket timeouts on POSIX systems.
-rw-r--r--include/violite.h6
-rw-r--r--libmysqld/lib_vio.c1
-rw-r--r--sql/net_serv.cc4
-rw-r--r--vio/viosocket.c26
4 files changed, 26 insertions, 11 deletions
diff --git a/include/violite.h b/include/violite.h
index 23fd694d355..ee19cbd62fe 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -77,7 +77,7 @@ my_bool vio_peer_addr(Vio* vio, char *buf, uint16 *port);
/* Remotes in_addr */
void vio_in_addr(Vio *vio, struct in_addr *in);
my_bool vio_poll_read(Vio *vio,uint timeout);
-void vio_timeout(Vio *vio,uint timeout);
+void vio_timeout(Vio *vio, uint which, uint timeout);
#ifdef HAVE_OPENSSL
#include <openssl/opensslv.h>
@@ -140,7 +140,7 @@ Vio *new_VioSSL(struct st_VioSSLAcceptorFd *fd, Vio *sd, int state);
#define vio_close(vio) ((vio)->vioclose)(vio)
#define vio_peer_addr(vio, buf, prt) (vio)->peer_addr(vio, buf, prt)
#define vio_in_addr(vio, in) (vio)->in_addr(vio, in)
-#define vio_timeout(vio, seconds) (vio)->timeout(vio, seconds)
+#define vio_timeout(vio, which, seconds) (vio)->timeout(vio, which, seconds)
#endif /* defined(HAVE_VIO) && !defined(DONT_MAP_VIO) */
/* This enumerator is used in parser - should be always visible */
@@ -180,7 +180,7 @@ struct st_vio
my_bool (*should_retry)(Vio*);
my_bool (*was_interrupted)(Vio*);
int (*vioclose)(Vio*);
- void (*timeout)(Vio*, unsigned int timeout);
+ void (*timeout)(Vio*, unsigned int which, unsigned int timeout);
void *ssl_arg;
#endif /* HAVE_VIO */
};
diff --git a/libmysqld/lib_vio.c b/libmysqld/lib_vio.c
index 0f5f7fda550..883080e8b92 100644
--- a/libmysqld/lib_vio.c
+++ b/libmysqld/lib_vio.c
@@ -229,6 +229,7 @@ my_bool vio_poll_read(Vio *vio,uint timeout)
void vio_timeout(Vio *vio __attribute__((unused)),
+ uint which __attribute__((unused)),
uint timeout __attribute__((unused)))
{
}
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 1e66bfc3e19..af54dd6b2f0 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -436,7 +436,7 @@ net_real_write(NET *net,const char *packet,ulong len)
thr_alarm(&alarmed,(uint) net->write_timeout,&alarm_buff);
#else
alarmed=0;
- vio_timeout(net->vio, net->write_timeout);
+ vio_timeout(net->vio, 1, net->write_timeout);
#endif /* NO_ALARM */
pos=(char*) packet; end=pos+len;
@@ -627,7 +627,7 @@ my_real_read(NET *net, ulong *complen)
if (net_blocking)
thr_alarm(&alarmed,net->read_timeout,&alarm_buff);
#else
- vio_timeout(net->vio, net->read_timeout);
+ vio_timeout(net->vio, 0, net->read_timeout);
#endif /* NO_ALARM */
pos = net->buff + net->where_b; /* net->packet -4 */
diff --git a/vio/viosocket.c b/vio/viosocket.c
index 7ea130c9949..2738f7743dc 100644
--- a/vio/viosocket.c
+++ b/vio/viosocket.c
@@ -345,12 +345,26 @@ my_bool vio_poll_read(Vio *vio,uint timeout)
}
-void vio_timeout(Vio *vio __attribute__((unused)),
- uint timeout __attribute__((unused)))
+void vio_timeout(Vio *vio, uint which, uint timeout)
{
+#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
+
#ifdef __WIN__
- ulong wait_timeout= (ulong) timeout * 1000;
- (void) setsockopt(vio->sd, SOL_SOCKET, SO_RCVTIMEO, (char*) &wait_timeout,
- sizeof(wait_timeout));
-#endif /* __WIN__ */
+
+ /* Windows expects time in milliseconds as int. */
+ int wait_timeout= (int) timeout * 1000;
+
+#else /* ! __WIN__ */
+
+ /* POSIX specifies time as struct timeval. */
+ struct timeval wait_timeout;
+ wait_timeout.tv_sec= timeout;
+ wait_timeout.tv_usec= 0;
+
+#endif /* ! __WIN__ */
+
+ (void) setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO,
+ (char*) &wait_timeout, sizeof(wait_timeout));
+
+#endif /* defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO) */
}