Skip to content

Commit 14508bb

Browse files
author
Kristofer Älvring
committed
WL#12999 Make the client get a better error message on wait_timeout
When the server terminates a client connection because of timeout, it tries to send an error message to the client. This message is later caught by the client on a best effort as the client discover that the write socket is terminated. Patch contributed by Mattias Jonsson @ booking. RB: 25049
1 parent 42abcc4 commit 14508bb

15 files changed

+214
-68
lines changed

Diff for: client/mysql.cc

+20-5
Original file line numberDiff line numberDiff line change
@@ -3042,11 +3042,19 @@ static int reconnect(void) {
30423042
return 0;
30433043
}
30443044

3045-
static void get_current_db() {
3045+
/**
3046+
Checks the current DB and updates the global variable current_db
3047+
If the command fails hen he current_db is set to nullptr.
3048+
3049+
@return Error state
3050+
@retval true An error occurred
3051+
@retval false Success; current_db is updated
3052+
*/
3053+
static bool get_current_db() {
30463054
MYSQL_RES *res;
30473055

30483056
/* If one_database is set, current_db is not supposed to change. */
3049-
if (one_database) return;
3057+
if (one_database) return false;
30503058

30513059
my_free(current_db);
30523060
current_db = nullptr;
@@ -3057,7 +3065,11 @@ static void get_current_db() {
30573065
if (row && row[0])
30583066
current_db = my_strdup(PSI_NOT_INSTRUMENTED, row[0], MYF(MY_WME));
30593067
mysql_free_result(res);
3068+
} else {
3069+
/* We failed to issue the command and we likely lost connection */
3070+
return true;
30603071
}
3072+
return false;
30613073
}
30623074

30633075
/***************************************************************************
@@ -3073,8 +3085,10 @@ static int mysql_real_query_for_lazy(const char *buf, size_t length,
30733085
if (set_params && global_attrs->set_params(&mysql)) break;
30743086
if (!mysql_real_query(&mysql, buf, (ulong)length)) break;
30753087
error = put_error(&mysql);
3076-
if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 ||
3077-
!opt_reconnect)
3088+
if ((mysql_errno(&mysql) != CR_SERVER_GONE_ERROR &&
3089+
mysql_errno(&mysql) != CR_SERVER_LOST &&
3090+
mysql.net.error != NET_ERROR_SOCKET_UNUSABLE) ||
3091+
retry > 1 || !opt_reconnect)
30783092
break;
30793093
if (reconnect()) break;
30803094
}
@@ -4270,8 +4284,9 @@ static int com_use(String *buffer MY_ATTRIBUTE((unused)), char *line) {
42704284
We need to recheck the current database, because it may change
42714285
under our feet, for example if DROP DATABASE or RENAME DATABASE
42724286
(latter one not yet available by the time the comment was written)
4287+
If this command fails we assume we lost connection.
42734288
*/
4274-
get_current_db();
4289+
if (get_current_db()) connected = false;
42754290

42764291
if (!current_db || cmp_database(charset_info, current_db, tmp)) {
42774292
if (one_database) {

Diff for: include/mysql_com.h

+6
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,12 @@ struct Vio;
876876
/// Default width for blob in bytes @todo - align this with sizes from field.h
877877
#define MAX_BLOB_WIDTH 16777216
878878

879+
#define NET_ERROR_UNSET 0 /**< No error has occurred yet */
880+
#define NET_ERROR_SOCKET_RECOVERABLE 1 /**< Socket still usable */
881+
#define NET_ERROR_SOCKET_UNUSABLE 2 /**< Do not use the socket */
882+
#define NET_ERROR_SOCKET_NOT_READABLE 3 /**< Try write and close socket */
883+
#define NET_ERROR_SOCKET_NOT_WRITABLE 4 /**< Try read and close socket */
884+
879885
typedef struct NET {
880886
MYSQL_VIO vio;
881887
unsigned char *buff, *buff_end, *write_pos, *read_pos;

Diff for: mysql-test/include/wait_until_connected_again.inc

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ while ($mysql_errno)
4040
# Strangely enough, the server might return "Too many connections"
4141
# while being shutdown, thus 1040 is an "allowed" error
4242
# See BUG#36228
43-
--error 0,1040,1053,2002,2003,2006,2013,1045,ER_SECURE_TRANSPORT_REQUIRED,2016,2017
43+
--error 0,1040,1053,2002,2003,2006,2013,1045,ER_SECURE_TRANSPORT_REQUIRED,2016,2017,ER_CLIENT_INTERACTION_TIMEOUT
4444
show session status;
4545
if ($mysql_errno == 1045){
4646
--let mysql_errno=0

Diff for: mysql-test/include/wait_until_disconnected.inc

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ if ($disconnect_timeout)
1111
let $mysql_errno= 0;
1212
while (!$mysql_errno)
1313
{
14-
--error 0,1040,1053,2002,2003,2006,2013,2016,2017
14+
--error 0,1040,1053,2002,2003,2006,2013,2016,2017,ER_CLIENT_INTERACTION_TIMEOUT
1515
show session status;
1616

1717
dec $counter;

Diff for: mysql-test/r/mysqltest.result

+1-1
Original file line numberDiff line numberDiff line change
@@ -1315,7 +1315,7 @@ SELECT 1 AS res;
13151315
res
13161316
1
13171317
SELECT 1 AS res;
1318-
ERROR HY000: MySQL server has gone away
1318+
Got one of the listed errors
13191319
#
13201320
# Bug#23743035: ADD A COPY_FILES_WILDCARD COMMAND
13211321
#

Diff for: mysql-test/r/ssl.result

+1-1
Original file line numberDiff line numberDiff line change
@@ -2275,6 +2275,6 @@ Ssl_cipher SSL_CIPHER
22752275
SET @@SESSION.wait_timeout = 2;
22762276
# Wait for ssl_con to be disconnected.
22772277
# Check that ssl_con has been disconnected.
2278-
# CR_SERVER_LOST, CR_SERVER_GONE_ERROR
2278+
# Different behavior depending on how the plattform implements the
22792279
SELECT 1;
22802280
Got one of the listed errors

Diff for: mysql-test/r/wait_timeout.result

+20-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ disconnection con1;
4242
SET @@SESSION.wait_timeout = 2;
4343
# Wait for con1 to be disconnected.
4444
# Check that con1 has been disconnected.
45-
# CR_SERVER_LOST, CR_SERVER_GONE_ERROR
4645
SELECT 1;
4746
Got one of the listed errors
4847
#
@@ -52,8 +51,27 @@ Got one of the listed errors
5251
SET @@SESSION.wait_timeout = 2;
5352
# Wait for con1 to be disconnected.
5453
# Check that con1 has been disconnected.
55-
# CR_SERVER_LOST, CR_SERVER_GONE_ERROR
54+
# Client interaction timeout
5655
SELECT 1;
5756
Got one of the listed errors
57+
SELECT "Check that we don't reconnect with reconnection disabled.";
58+
Got one of the listed errors
59+
#
60+
# Test UNIX domain sockets timeout with reconnect.
61+
#
62+
# Open con2 and set a timeout.
63+
--enable_reconnect;
64+
SET @is_old_connection = 1;
65+
SELECT @is_old_connection;
66+
@is_old_connection
67+
1
68+
SET @@SESSION.wait_timeout = 2;
69+
# Wait for con2 to be disconnected.
70+
# Check that con2 has been reconnected.
71+
SELECT "Unix domain socket will hit wait_timeout with reconnect";
72+
Got one of the listed errors
73+
SELECT @is_old_connection;
74+
@is_old_connection
75+
NULL
5876
# must find the pattern
5977
Pattern "The wait_timeout period was exceeded, the idle time since last command was too long." found

Diff for: mysql-test/t/mysqltest.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -3287,7 +3287,7 @@ SELECT 1 AS res;
32873287
disconnect con1;
32883288
--source include/wait_until_disconnected.inc
32893289

3290-
--error CR_SERVER_GONE_ERROR
3290+
--error CR_SERVER_GONE_ERROR,CR_SERVER_LOST
32913291
SELECT 1 AS res;
32923292

32933293
connection default;

Diff for: mysql-test/t/ssl.test

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ let $wait_condition=
4848

4949
--echo # Check that ssl_con has been disconnected.
5050
connection ssl_con;
51-
--echo # CR_SERVER_LOST, CR_SERVER_GONE_ERROR
52-
--error 2006,2013
51+
--echo # Different behavior depending on how the plattform implements the
52+
--error ER_CLIENT_INTERACTION_TIMEOUT,CR_SERVER_LOST
5353
SELECT 1;
5454

5555
connection default;

Diff for: mysql-test/t/wait_timeout.test

+40-9
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ connection default;
6666
# When the connection is closed in this way, the error code should
6767
# be consistent see Bug#2845 for an explanation
6868
# depending on platform/client, either errno 2006 or 2013 can occur below
69-
--error 2006,2013
69+
--error ER_CLIENT_INTERACTION_TIMEOUT,CR_SERVER_LOST
7070
SELECT 2;
7171
--echo --enable_reconnect;
7272
--enable_reconnect
@@ -123,7 +123,7 @@ connection con1;
123123
# When the connection is closed in this way, the error code should
124124
# be consistent see Bug#2845 for an explanation
125125
# depending on platform/client, either errno 2006 or 2013 can occur below
126-
--error 2006,2013
126+
--error ER_CLIENT_INTERACTION_TIMEOUT,CR_SERVER_LOST
127127
SELECT 2;
128128
--echo --enable_reconnect;
129129
--enable_reconnect
@@ -148,6 +148,7 @@ connect (default,localhost,root,,test,,);
148148
--echo # Open con1 and set a timeout.
149149
connect(con1,localhost,root,,);
150150

151+
--disable_reconnect
151152
LET $ID= `SELECT connection_id()`;
152153
SET @@SESSION.wait_timeout = 2;
153154

@@ -160,8 +161,7 @@ let $wait_condition=
160161

161162
--echo # Check that con1 has been disconnected.
162163
connection con1;
163-
--echo # CR_SERVER_LOST, CR_SERVER_GONE_ERROR
164-
--error 2006,2013
164+
--error ER_CLIENT_INTERACTION_TIMEOUT,CR_SERVER_LOST
165165
SELECT 1;
166166

167167
disconnect con1;
@@ -172,7 +172,7 @@ connection default;
172172
--echo #
173173

174174
--echo # Open con1 and set a timeout.
175-
connect(con1,127.0.0.1,root,,);
175+
connect(con1,127.0.0.1,root,,,,,TCP,,);
176176

177177
LET $ID= `SELECT connection_id()`;
178178
SET @@SESSION.wait_timeout = 2;
@@ -186,16 +186,47 @@ let $wait_condition=
186186

187187
--echo # Check that con1 has been disconnected.
188188
connection con1;
189-
--echo # CR_SERVER_LOST, CR_SERVER_GONE_ERROR
190-
--error 2006,2013
189+
--disable_reconnect
190+
--echo # Client interaction timeout
191+
--error ER_CLIENT_INTERACTION_TIMEOUT,CR_SERVER_LOST
191192
SELECT 1;
192193

193-
disconnect con1;
194+
--error ER_CLIENT_INTERACTION_TIMEOUT,CR_SERVER_LOST
195+
SELECT "Check that we don't reconnect with reconnection disabled.";
196+
197+
--echo #
198+
--echo # Test UNIX domain sockets timeout with reconnect.
199+
--echo #
200+
201+
--echo # Open con2 and set a timeout.
202+
connect(con2,localhost,root,,);
203+
204+
--echo --enable_reconnect;
205+
--enable_reconnect
206+
SET @is_old_connection = 1;
207+
SELECT @is_old_connection;
208+
209+
LET $ID= `SELECT connection_id()`;
210+
SET @@SESSION.wait_timeout = 2;
211+
212+
--echo # Wait for con2 to be disconnected.
194213
connection default;
214+
let $wait_condition=
215+
SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST
216+
WHERE ID = $ID;
217+
--source include/wait_condition.inc
195218

219+
--echo # Check that con2 has been reconnected.
220+
connection con2;
221+
--error ER_CLIENT_INTERACTION_TIMEOUT,CR_SERVER_LOST
222+
SELECT "Unix domain socket will hit wait_timeout with reconnect";
223+
SELECT @is_old_connection;
224+
connection default;
225+
--disable_reconnect
226+
disconnect con2;
227+
disconnect con1;
196228
# Wait till all disconnects are completed
197229
--source include/wait_until_count_sessions.inc
198-
199230
#
200231
# Bug #28940167 WAIT_TIMEOUT ERROR NOT CLEAR AND NOT SENT TO CLIENT BEFORE CLOSING CONNECTION
201232
#

Diff for: share/messages_to_clients.txt

+3
Original file line numberDiff line numberDiff line change
@@ -9502,6 +9502,9 @@ ER_TABLE_MUST_HAVE_A_VISIBLE_COLUMN
95029502
ER_WARN_IMPORT_COMPRESSION_FAIL
95039503
eng "Compression failed while doing import with the following error : %s"
95049504

9505+
ER_CLIENT_INTERACTION_TIMEOUT
9506+
eng "The client was disconnected by the server because of inactivity. See wait_timeout and interactive_timeout for configuring this behavior."
9507+
95059508
#
95069509
# End of 8.0 error messages (server-to-client).
95079510
# Do NOT add messages intended for the error log above!

0 commit comments

Comments
 (0)