Commit bac6523d authored by Ahmad Abdullateef's avatar Ahmad Abdullateef

BUG#14727815 - CRASH IN PTHREAD_RWLOCK_WRLOCK/SRW_UNLOCK

                             IN QUERY CACHE CODE

DESCRIPTION:
MySQL Server crashes sporadically when Query Caching is on and
the server has high contention among clients. 


ANALYSIS :

Scenario 1:
In Query_cache::move_by_type() when handling RESULT or its related blocks,
Write Lock is acquired on its parent Query block. However the next and prev
pointers are cached in local variables before lock acquisition. In an extremely
high contention scenario there exists a possibility that
Query_cache::append_result_data() is operating on the same query block
and as a consequence might append a new Result block to the end of Result
blocks Linked List of the Query. This would manipulate the next, prev pointers
of the Block being processed in move_by_type(), however the local pointers
still point to previous nodes there by causing Data Corruption leading to crash.

Scenario 2:
In Windows SDK "BOOL" is typedefed as "int" and BOOLEAN is typedefed as
"usigned char". The function pointer definition "srw_bool_func" mistakenly uses 
BOOL instead of BOOLEAN thereby virtually making the function 
my_TryAcquireSRWLockExclusive() always succeed because only the LSB of EAX
has the actual result of the call, however due to type mismatch all bytes of EAX
are used for evaluation. Again during high contention scenarios in 
Query_cache::free_old_query() calls try_lock_writing() on a Query, this call 
always succeeds and the query is freed, even though it is used by some other
thread, in this case Query_cache::send_result_to_client() was using it and the
code causes a crash because it accessed free or reallocated memory.

FIX :

Scenario 1:
The next, prev pointers are now accessed only after Lock acquisition in 
Query_cache::move_by_type().

Scenario 2:
In the definition of "srw_bool_func" BOOL has been replaced with "BOOLEAN"
parents 328430b4 6d82d9c9
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
static BOOL have_srwlock= FALSE; static BOOL have_srwlock= FALSE;
/* Prototypes and function pointers for windows functions */ /* Prototypes and function pointers for windows functions */
typedef VOID (WINAPI* srw_func) (PSRWLOCK SRWLock); typedef VOID (WINAPI* srw_func) (PSRWLOCK SRWLock);
typedef BOOL (WINAPI* srw_bool_func) (PSRWLOCK SRWLock); typedef BOOLEAN (WINAPI* srw_bool_func) (PSRWLOCK SRWLock);
static srw_func my_InitializeSRWLock; static srw_func my_InitializeSRWLock;
static srw_func my_AcquireSRWLockExclusive; static srw_func my_AcquireSRWLockExclusive;
......
...@@ -3971,11 +3971,10 @@ my_bool Query_cache::move_by_type(uchar **border, ...@@ -3971,11 +3971,10 @@ my_bool Query_cache::move_by_type(uchar **border,
(int) block->type)); (int) block->type));
if (*border == 0) if (*border == 0)
break; break;
Query_cache_block *query_block = block->result()->parent(), Query_cache_block *query_block= block->result()->parent();
*next = block->next,
*prev = block->prev;
Query_cache_block::block_type type = block->type;
BLOCK_LOCK_WR(query_block); BLOCK_LOCK_WR(query_block);
Query_cache_block *next= block->next, *prev= block->prev;
Query_cache_block::block_type type= block->type;
ulong len = block->length, used = block->used; ulong len = block->length, used = block->used;
Query_cache_block *pprev = block->pprev, Query_cache_block *pprev = block->pprev,
*pnext = block->pnext, *pnext = block->pnext,
......
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