summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <msvensson@neptunus.(none)>2006-02-16 12:02:38 +0100
committerunknown <msvensson@neptunus.(none)>2006-02-16 12:02:38 +0100
commit074e15acf10fd87da10f1fa0db944dac73714839 (patch)
tree90ada62285927ff547b71f85b69ed2a228a4dfc1
parent8ab48d88b69b932415687696b45358608369cb01 (diff)
downloadmariadb-git-074e15acf10fd87da10f1fa0db944dac73714839.tar.gz
Bug#2845 client fails to reconnect if using TCP/IP
- Detect that connection to server has been broken in "net_clear". Since net_clear is always called before we send command to server, we can be sure that server has not received the command. mysql-test/r/wait_timeout.result: Update test result mysql-test/t/wait_timeout-master.opt: Decrease wait_timeout value to avoid unneccessary sleeps mysql-test/t/wait_timeout.test: Test that same error message is returned when disconnected regardless of connection is socket or TCP Decrease sleep times sql/net_serv.cc: Make "net_clear" detect if connection with server has been broken by performing a select. If the select returns that there are data to read but no data can be read, that means the connection is broken. Signal disconnected to "write" functions by setting error to 2.
-rw-r--r--mysql-test/r/wait_timeout.result8
-rw-r--r--mysql-test/t/wait_timeout-master.opt2
-rw-r--r--mysql-test/t/wait_timeout.test20
-rw-r--r--sql/net_serv.cc85
4 files changed, 101 insertions, 14 deletions
diff --git a/mysql-test/r/wait_timeout.result b/mysql-test/r/wait_timeout.result
index 56232e481c0..683986abf5d 100644
--- a/mysql-test/r/wait_timeout.result
+++ b/mysql-test/r/wait_timeout.result
@@ -6,3 +6,11 @@ ERROR HY000: MySQL server has gone away
select 3;
3
3
+select 1;
+1
+1
+select 2;
+ERROR HY000: MySQL server has gone away
+select 3;
+3
+3
diff --git a/mysql-test/t/wait_timeout-master.opt b/mysql-test/t/wait_timeout-master.opt
index 0ad622e9677..9e5c2289eb2 100644
--- a/mysql-test/t/wait_timeout-master.opt
+++ b/mysql-test/t/wait_timeout-master.opt
@@ -1 +1 @@
---wait-timeout=2
+--wait-timeout=1
diff --git a/mysql-test/t/wait_timeout.test b/mysql-test/t/wait_timeout.test
index 26f91569868..1c9efa7c07d 100644
--- a/mysql-test/t/wait_timeout.test
+++ b/mysql-test/t/wait_timeout.test
@@ -3,9 +3,25 @@
#
--disable_reconnect
select 1;
-# wait_timeout is 2, so we should get disconnected now
---sleep 5
+# wait_timeout is 1, so we should get disconnected now
+--sleep 2
+# When the connection is closed in this way, the error code should
+# be consistent see bug#2845 for an explanation
--error 2006
select 2;
--enable_reconnect
select 3;
+
+# Do the same test as above on a TCP connection
+connect (con1,127.0.0.1,root,,test,$MASTER_MYPORT,);
+--disable_reconnect
+select 1;
+# wait_timeout is 1, so we should get disconnected now
+--sleep 2
+# When the connection is closed in this way, the error code should
+# be consistent see bug#2845 for an explanation
+--error 2006
+select 2;
+--enable_reconnect
+select 3;
+disconnect con1;
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 7326c0395e3..ef56f0d77e2 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -194,30 +194,93 @@ my_bool net_realloc(NET *net, ulong length)
DBUG_RETURN(0);
}
- /* Remove unwanted characters from connection */
+
+/*
+ Check if there is any data to be read from the socket
+
+ SYNOPSIS
+ net_data_is_ready()
+ sd socket descriptor
+
+ DESCRIPTION
+ Check if there is any data to be read from the socket.
+
+ RETURN VALUES
+ 0 No data to read
+ 1 Data or EOF to read
+*/
+
+static my_bool net_data_is_ready(my_socket sd)
+{
+ fd_set sfds;
+ struct timeval tv;
+ int res;
+
+ FD_ZERO(&sfds);
+ FD_SET(sd, &sfds);
+
+ tv.tv_sec= tv.tv_usec= 0;
+
+ if ((res= select(sd+1, &sfds, NULL, NULL, &tv)) < 0)
+ return FALSE;
+ else
+ return test(res ? FD_ISSET(sd, &sfds) : 0);
+}
+
+
+/*
+ Remove unwanted characters from connection
+ and check if disconnected
+
+ SYNOPSIS
+ net_clear()
+ net NET handler
+
+ DESCRIPTION
+ Read from socket until there is nothing more to read. Discard
+ what is read.
+
+ If there is anything when to read 'net_clear' is called this
+ normally indicates an error in the protocol.
+
+ When connection is properly closed (for TCP it means with
+ a FIN packet), then select() considers a socket "ready to read",
+ in the sense that there's EOF to read, but read() returns 0.
+
+*/
void net_clear(NET *net)
{
+ int count;
DBUG_ENTER("net_clear");
-#if !defined(EXTRA_DEBUG) && !defined(EMBEDDED_LIBRARY)
+#if !defined(EMBEDDED_LIBRARY)
+ while(net_data_is_ready(net->vio->sd))
{
- int count; /* One may get 'unused' warn */
- my_bool old_mode;
- if (!vio_blocking(net->vio, FALSE, &old_mode))
+ /* The socket is ready */
+ if ((count= vio_read(net->vio, (char*) (net->buff),
+ (uint32) net->max_packet)) > 0)
{
- while ((count = vio_read(net->vio, (char*) (net->buff),
- (uint32) net->max_packet)) > 0)
- DBUG_PRINT("info",("skipped %d bytes from file: %s",
- count, vio_description(net->vio)));
- vio_blocking(net->vio, TRUE, &old_mode);
+ DBUG_PRINT("info",("skipped %d bytes from file: %s",
+ count, vio_description(net->vio)));
+#ifdef EXTRA_DEBUG
+ fprintf(stderr,"skipped %d bytes from file: %s\n",
+ count, vio_description(net->vio));
+#endif
+ }
+ else
+ {
+ DBUG_PRINT("info",("socket ready but only EOF to read - disconnected"));
+ net->error= 2;
+ break;
}
}
-#endif /* EXTRA_DEBUG */
+#endif
net->pkt_nr=net->compress_pkt_nr=0; /* Ready for new command */
net->write_pos=net->buff;
DBUG_VOID_RETURN;
}
+
/* Flush write_buffer if not empty. */
my_bool net_flush(NET *net)