From: Date: August 22 2007 11:17am Subject: bk commit into 5.0 tree (gshchepa:1.2498) BUG#30201 List-Archive: http://lists.mysql.com/commits/32858 X-Bug: 30201 Message-Id: <20070822091742.48D3C3D43AF@localhost.localdomain> Below is the list of changes that have just been committed into a local 5.0 repository of uchum. When uchum does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-08-22 14:17:35+05:00, gshchepa@stripped +1 -0 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@stripped, 2007-08-22 14:14:09+05:00, gshchepa@stripped +21 -16 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. diff -Nrup a/sql/sql_cache.cc b/sql/sql_cache.cc --- a/sql/sql_cache.cc 2007-05-10 17:54:53 +05:00 +++ b/sql/sql_cache.cc 2007-08-22 14:14:09 +05:00 @@ -706,6 +706,12 @@ void query_cache_end_of_result(THD *thd) Query_cache_block *query_block; DBUG_ENTER("query_cache_end_of_result"); + if (thd->killed) + { + query_cache_abort(&thd->net); + DBUG_VOID_RETURN; + } + /* See the comment on double-check locking usage above. */ if (thd->net.query_cache_query == 0) DBUG_VOID_RETURN; @@ -727,27 +733,26 @@ 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__, ""); - - /* - 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). - */ + DBUG_PRINT("error", ("End of data with no result blocks; " + "Query '%s' removed from cache.", header->query())); + + BLOCK_UNLOCK_WR(query_block); + 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);