Commit 2ebee313 authored by unknown's avatar unknown

A fix for Bug#35289: Too many connections -- wrong SQL state

in some case.

ER_CON_COUNT_ERROR is defined with SQL state 08004. However, this SQL state is not always
returned.

This error can be thrown in two cases:

  1. when an ordinary user (a user w/o SUPER privilege) is connecting,
    and the number of active user connections is equal or greater than
    max_connections.

  2. when a user is connecting and the number of active user connections is
    already (max_connections + 1) -- that means that no more connections will
    be accepted regardless of the user credentials.

In the 1-st case, SQL state is correct.

The bug happens in the 2-nd case -- on UNIX the client gets 00000 SQL state, which is
absolutely wrong (00000 means "not error SQL state); on Windows
the client accidentally gets HY000 (which means "unknown SQL state).

The cause of the problem is that the server rejects extra connection
prior to read a packet with client capabilities. Thus, the server
does not know if the client supports SQL states or not (if the client
supports 4.1 protocol or not). So, the server supposes the worst and
does not send SQL state at all.

The difference in behavior on UNIX and Windows occurs because on Windows
CLI_MYSQL_REAL_CONNECT() invokes create_shared_memory(), which returns
an error (in default configuration, where shared memory is not configured).
Then, the client does not reset this error, so when the connection is
rejected, SQL state is HY000 (from the error from create_shared_memory()).

The bug appeared after test case for Bug#33507 -- before that, this behavior
just had not been tested.

The fix is to 1) reset the error after create_shared_memory();
2) set SQL state to 'unknown error' if it was not received from
the server.

A separate test case is not required, since the behavior is already
tested in connect.test.

Note for doc-team: the manual should be updated to say that under
some circumstances, 'Too many connections' has HY000 SQL state.


mysql-test/r/connect.result:
  Update result file.
sql-common/client.c:
  1. Reset an error from create_shared_memory();
  2. Set SQL state to 'unknown error' if it was not received from
     the server.
parent 64cba9ba
...@@ -150,7 +150,7 @@ ERROR 08004: Too many connections ...@@ -150,7 +150,7 @@ ERROR 08004: Too many connections
# -- Connecting super (1)... # -- Connecting super (1)...
# -- Connecting super (2)... # -- Connecting super (2)...
ERROR 00000: Too many connections ERROR HY000: Too many connections
SELECT user FROM information_schema.processlist ORDER BY id; SELECT user FROM information_schema.processlist ORDER BY id;
user user
......
...@@ -684,6 +684,16 @@ cli_safe_read(MYSQL *mysql) ...@@ -684,6 +684,16 @@ cli_safe_read(MYSQL *mysql)
strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH); strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH);
pos+= SQLSTATE_LENGTH+1; pos+= SQLSTATE_LENGTH+1;
} }
else
{
/*
The SQL state hasn't been received -- it should be reset to HY000
(unknown error sql state).
*/
strmov(net->sqlstate, unknown_sqlstate);
}
(void) strmake(net->last_error,(char*) pos, (void) strmake(net->last_error,(char*) pos,
min((uint) len,(uint) sizeof(net->last_error)-1)); min((uint) len,(uint) sizeof(net->last_error)-1));
} }
...@@ -1897,7 +1907,13 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ...@@ -1897,7 +1907,13 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
(int) have_tcpip)); (int) have_tcpip));
if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY)
goto error; goto error;
/* Try also with PIPE or TCP/IP */
/*
Try also with PIPE or TCP/IP. Clear the error from
create_shared_memory().
*/
net_clear_error(net);
} }
else else
{ {
......
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