diff options
author | unknown <anozdrin/alik@ibm.> | 2007-11-30 16:12:20 +0300 |
---|---|---|
committer | unknown <anozdrin/alik@ibm.> | 2007-11-30 16:12:20 +0300 |
commit | 4b954cc094d2082982a1ac2cab99d1e905309048 (patch) | |
tree | 9d9e129506ee56e40def9af807200245632fb7a9 /sql/protocol.cc | |
parent | 90477e23e225170ee1c84067cdc1d612cc2978f6 (diff) | |
download | mariadb-git-4b954cc094d2082982a1ac2cab99d1e905309048.tar.gz |
A patch for BUG#32148: killing a query may be ineffective.
The problem was that THD::killed was reset after a command was
read from the socket, but before it was actually handled. That lead
to a race: if another KILL statement was issued for this connection
in the middle of reading from the socket and processing a command,
THD::killed state would be cleaned.
The fix is to move this cleanup into net_send_error() function.
A sample test case exists in binlog_killed.test:
- connection 1: start a new transaction on table t1;
- connection 2: send query to the server (w/o waiting for the
result) to update data in table t1 -- this query will be blocked
since there is unfinished transaction;
- connection 1: kill query in connection 2 and finish the transaction;
- connection 2: get result of the previous query -- it should be
the "query-killed" error.
This test however contains race condition, which can not be fixed
with the current protocol: there is no way to guarantee, that the
server will receive and start processing the query in connection 2
(which is intended to get blocked) before the KILL command (sent in
the connection 1) will arrive. In other words, there is no way to
ensure that the following sequence will not happen:
- connection 1: start a new transaction on table t1;
- connection 1: kill query in connection 2 and finish the transaction;
- connection 2: send query to the server (w/o waiting for the
result) to update data in table t1 -- this query will be blocked
since there is unfinished transaction;
- connection 2: get result of the previous query -- the query will
succeed.
So, there is no test case for this bug, since it's impossible
to write a reliable test case under the current circumstances.
sql/protocol.cc:
Move thd->killed cleanup from dispatch_command() to net_send_error().
sql/sql_parse.cc:
Move thd->killed cleanup from dispatch_command() to net_send_error().
Diffstat (limited to 'sql/protocol.cc')
-rw-r--r-- | sql/protocol.cc | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/sql/protocol.cc b/sql/protocol.cc index bf8faec006a..713f4ed3d25 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -76,6 +76,12 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) DBUG_ASSERT(!thd->spcont); + if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA) + { + thd->killed= THD::NOT_KILLED; + thd->mysys_var->abort= 0; + } + if (net && net->no_send_error) { thd->clear_error(); |