Bug #55223 | assert in Protocol::end_statement during CREATE DATABASE | ||
---|---|---|---|
Submitted: | 13 Jul 2010 17:00 | Modified: | 12 Aug 2010 19:58 |
Reporter: | Matthias Leich | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server | Severity: | S3 (Non-critical) |
Version: | 5.5.6-m3-debug-log | OS: | Any |
Assigned to: | Jon Olav Hauglid | CPU Architecture: | Any |
Tags: | assert |
[13 Jul 2010 17:00]
Matthias Leich
[14 Jul 2010 17:03]
Jon Olav Hauglid
Simplified grammar: query: CREATE DATABASE testdb_N | SELECT MIN(id) INTO @kill_id FROM executors; KILL QUERY @kill_id; query_init: CREATE TABLE executors (id INT); INSERT INTO executors SET id = CONNECTION_ID(); For the connection doing CREATE DATABASE: (gdb) p thd->killed $1 = THD::KILL_QUERY (gdb) p thd->mysys_var->abort $2 = 1 So it looks like doing KILL QUERY on the connection doing CREATE DATABASE at the wrong moment causes this assert to be triggered. I've verified that it's possible to trigger this assert for other statements in a similar way.
[20 Jul 2010 11:26]
Jon Olav Hauglid
More details: CREATE DATABASE is aborted by KILL QUERY while CREATE DATABASE is waiting on a metadata lock (introduced by the 5.5 patch for bug#54360). CREATE DATABASE exits with mysys_var->abort=1 but without thd->killed set. Since CREATE DATABASE fails, my_ok() won't be called, and since thd->killed is not set, thd->send_kill_message() is not called either. This triggers the assert. THD::awake used by KILL QUERY sets thd->killed before mysys_var->abort, but this must have been reordered by the compiler.
[20 Jul 2010 13:41]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/113953 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.
[21 Jul 2010 15:00]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/114049 3081 Jon Olav Hauglid 2010-07-21 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.
[22 Jul 2010 8:01]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/114113 3081 Jon Olav Hauglid 2010-07-22 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 was 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. Also, both values are reset at the end of statement execution. This means that it is possible for KILL QUERY to first set thd->killed, then have the killed statement reset both thd->killed and mysys_var->abort and finally have KILL QUERY set mysys_var->abort. This means that the connection with the killed statement will start executing the next statement with the two values out of sync - i.e. thd->killed not set but mysys_var->abort set. Since mysys_var->abort is used to check if a wait for a metadata lock should be aborted, the next statement would immediately abort any such waiting. When 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. But since the->killed had been reset, neither OK nor an error message was sent to the client. This then triggered the assert. 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. The patch has been checked using RQG and the grammar posted on the bug report.
[22 Jul 2010 8:36]
Jon Olav Hauglid
Pushed to mysql-trunk-runtime (Ver 5.5.6).
[4 Aug 2010 7:53]
Bugs System
Pushed into mysql-trunk 5.5.6-m3 (revid:alik@sun.com-20100731131027-1n61gseejyxsqk5d) (version source revid:marko.makela@oracle.com-20100621094008-o9fa153s3f09merw) (merge vers: 5.1.49) (pib:18)
[4 Aug 2010 8:04]
Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804080001-bny5271e65xo34ig) (version source revid:marko.makela@oracle.com-20100621094008-o9fa153s3f09merw) (merge vers: 5.1.49) (pib:18)
[4 Aug 2010 8:20]
Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804081533-c1d3rbipo9e8rt1s) (version source revid:marko.makela@oracle.com-20100621094008-o9fa153s3f09merw) (merge vers: 5.1.49) (pib:18)
[4 Aug 2010 9:01]
Bugs System
Pushed into mysql-next-mr (revid:alik@ibmvm-20100804081630-ntapn8bf9pko9vj3) (version source revid:marko.makela@oracle.com-20100621094008-o9fa153s3f09merw) (pib:20)
[12 Aug 2010 19:58]
Paul DuBois
Noted in 5.5.6 changelog. A statement that was aborted by KILL QUERY while it waited on a metadata lock could raise an assertion in debug builds, or send OK to the client instead of ER_QUERY_INTERRUPTED in regular builds.