#At file:///export/home/x/mysql-trunk-runtime-bug55223/ based on revid:jon.hauglid@stripped
3081 Jon Olav Hauglid 2010-07-20
Bug #55223 assert in Protocol::end_statement during CREATE DATABASE
The problem was that a statement could cause an assert if it was aborted by
KILL QUERY while it waited on a metadata lock. This assert checks that a
statement either sends OK or an error to the client. If the bug was triggered
on release builds, it caused OK to be sent to the client instead of
ER_QUERY_INTERRUPTED.
The root cause of the problem is that there are two separate ways to tell if a
statement is killed: thd->killed and mysys_var->abort. KILL QUERY causes both
to be set, thd->killed before mysys_var->abort. The latter was used to check
if a wait for a metadata lock should be aborted. If waiting is aborted, no OK
message is sent and thd->killed is checked to see if ER_QUERY_INTERRUPTED
should be sent to the client. The assert could be triggered if the compiler
reordered the KILL QUERY code so that mysys_var->abort was set before
thd->killed, and the aborted statement reached the thd->killed check before
thd->killed was set by KILL QUERY.
This patch fixes the problem by changing the metadata lock waiting code to
check thd->killed.
No test case added as reproducing the assert is dependent on very exact timing
of two (or more) threads and compiler reording of instructions. The patch has
been checked using RQG and the grammar posted on the bug report.
modified:
sql/mdl.cc
=== modified file 'sql/mdl.cc'
--- a/sql/mdl.cc 2010-07-13 18:01:54 +0000
+++ b/sql/mdl.cc 2010-07-20 13:39:59 +0000
@@ -1029,7 +1029,7 @@ MDL_wait::timed_wait(THD *thd, struct ti
old_msg= MDL_ENTER_COND(thd, mysys_var, &m_COND_wait_status,
&m_LOCK_wait_status);
- while (!m_wait_status && !mysys_var->abort &&
+ while (!m_wait_status && !thd_killed(thd) &&
wait_result != ETIMEDOUT && wait_result != ETIME)
wait_result= mysql_cond_timedwait(&m_COND_wait_status, &m_LOCK_wait_status,
abs_timeout);
@@ -1048,7 +1048,7 @@ MDL_wait::timed_wait(THD *thd, struct ti
false, which means that the caller intends to restart the
wait.
*/
- if (mysys_var->abort)
+ if (thd_killed(thd))
m_wait_status= KILLED;
else if (set_status_on_timeout)
m_wait_status= TIMEOUT;
Attachment: [text/bzr-bundle] bzr/jon.hauglid@oracle.com-20100720133959-vhzi5tlk2krwqr1w.bundle
| Thread |
|---|
| • bzr commit into mysql-trunk-runtime branch (jon.hauglid:3081) Bug#55223 | Jon Olav Hauglid | 20 Jul |