diff options
author | unknown <gshchepa/uchum@gleb.loc> | 2007-08-22 18:15:54 +0500 |
---|---|---|
committer | unknown <gshchepa/uchum@gleb.loc> | 2007-08-22 18:15:54 +0500 |
commit | 891b1659fcd0d0a65b2a6d8ccd40e9225b76bb88 (patch) | |
tree | 822d9e3b8b29ae32c681ec759d0d437912cdcc9e | |
parent | 92abaeee0c05ba5e1b074a4aff308789d4ecee12 (diff) | |
download | mariadb-git-891b1659fcd0d0a65b2a6d8ccd40e9225b76bb88.tar.gz |
Fixed bug #30201.
Killing a SELECT query with KILL QUERY or KILL CONNECTION
causes a server crash if the query cache is enabled.
Normal evaluation of a query may be interrupted by the
KILL QUERY/CONNECTION statement, in this case the mysql_execute_command
function returns TRUE, and the thd->killed flag has true value.
In this case the result of the query may
be cached incompletely (omitting call to query_cache_insert inside
the net_real_write function), and next call to query_cache_end_of_result
may lead to server crash.
Thus, the query_cache_end_of_result function has been modified to abort
query cache in the case of killed thread.
sql/sql_cache.cc:
Fixed bug #30201.
The query_cache_end_of_result function has been modified to abort query
cache in the case of query execution failure. Also this function has been
modified to remove incomplete query block.
-rw-r--r-- | sql/sql_cache.cc | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 33d658ce6a1..0d8ef568550 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -710,6 +710,12 @@ void query_cache_end_of_result(THD *thd) if (thd->net.query_cache_query == 0) DBUG_VOID_RETURN; + if (thd->killed) + { + query_cache_abort(&thd->net); + DBUG_VOID_RETURN; + } + #ifdef EMBEDDED_LIBRARY query_cache_insert(&thd->net, (char*)thd, emb_count_querycache_size(thd)); @@ -727,27 +733,30 @@ void query_cache_end_of_result(THD *thd) DUMP(&query_cache); BLOCK_LOCK_WR(query_block); Query_cache_query *header= query_block->query(); - Query_cache_block *last_result_block= header->result()->prev; - ulong allign_size= ALIGN_SIZE(last_result_block->used); - ulong len= max(query_cache.min_allocation_unit, allign_size); - if (last_result_block->length >= query_cache.min_allocation_unit + len) - query_cache.split_block(last_result_block,len); + Query_cache_block *last_result_block; + ulong allign_size; + ulong len; -#ifndef DBUG_OFF if (header->result() == 0) { - DBUG_PRINT("error", ("end of data whith no result. query '%s'", - header->query())); - query_cache.wreck(__LINE__, ""); - + DBUG_PRINT("error", ("End of data with no result blocks; " + "Query '%s' removed from cache.", header->query())); /* - We do not need call of BLOCK_UNLOCK_WR(query_block); here because - query_cache.wreck() switched query cache off but left content - untouched for investigation (it is debugging method). + Extra safety: empty result should not happen in the normal call + to this function. In the release version that query should be ignored + and removed from QC. */ + DBUG_ASSERT(0); + query_cache.free_query(query_block); goto end; } -#endif + + last_result_block= header->result()->prev; + allign_size= ALIGN_SIZE(last_result_block->used); + len= max(query_cache.min_allocation_unit, allign_size); + if (last_result_block->length >= query_cache.min_allocation_unit + len) + query_cache.split_block(last_result_block,len); + header->found_rows(current_thd->limit_found_rows); header->result()->type= Query_cache_block::RESULT; header->writer(0); |