summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <gshchepa/uchum@gleb.loc>2007-08-22 18:15:54 +0500
committerunknown <gshchepa/uchum@gleb.loc>2007-08-22 18:15:54 +0500
commit891b1659fcd0d0a65b2a6d8ccd40e9225b76bb88 (patch)
tree822d9e3b8b29ae32c681ec759d0d437912cdcc9e
parent92abaeee0c05ba5e1b074a4aff308789d4ecee12 (diff)
downloadmariadb-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.cc37
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);