Skip to content

Commit e8d19b9

Browse files
author
Alexander Nozdrin
committed
Auto-merge from mysql-next-4284.
2 parents 04d77e8 + 68710e2 commit e8d19b9

File tree

9 files changed

+185
-4
lines changed

9 files changed

+185
-4
lines changed

mysql-test/include/handler.inc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,3 +1681,25 @@ handler t1 close;
16811681
--echo # Clean-up.
16821682
drop function f1;
16831683
drop tables t1, t2;
1684+
1685+
1686+
--echo #
1687+
--echo # Test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY +
1688+
--echo # HANDLER + LOCK + SP".
1689+
--echo # Also see additional coverage for this bug in flush.test.
1690+
--echo #
1691+
--disable_warnings
1692+
drop tables if exists t1, t2;
1693+
--enable_warnings
1694+
create table t1 (i int);
1695+
create temporary table t2 (j int);
1696+
handler t1 open;
1697+
lock table t2 read;
1698+
--echo # This commit should not release any MDL locks.
1699+
commit;
1700+
unlock tables;
1701+
--echo # The below statement crashed before the bug fix as it
1702+
--echo # has attempted to release metadata lock which was
1703+
--echo # already released by commit.
1704+
handler t1 close;
1705+
drop tables t1, t2;

mysql-test/r/flush.result

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,20 @@ unlock tables;
9494
set global general_log= @old_general_log;
9595
set global read_only= @old_read_only;
9696
End of 5.1 tests
97+
#
98+
# Additional test for bug #51136 "Crash in pthread_rwlock_rdlock
99+
# on TEMPORARY + HANDLER + LOCK + SP".
100+
# Also see the main test for this bug in include/handler.inc.
101+
#
102+
drop tables if exists t1, t2;
103+
create table t1 (i int);
104+
create temporary table t2 (j int);
105+
flush tables with read lock;
106+
lock table t2 read;
107+
# This commit should not release any MDL locks.
108+
commit;
109+
# The below statement crashed before the bug fix as it
110+
# has attempted to release global shared metadata lock
111+
# which was already released by commit.
112+
unlock tables;
113+
drop tables t1, t2;

mysql-test/r/handler_innodb.result

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,3 +1667,21 @@ handler t1 close;
16671667
# Clean-up.
16681668
drop function f1;
16691669
drop tables t1, t2;
1670+
#
1671+
# Test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY +
1672+
# HANDLER + LOCK + SP".
1673+
# Also see additional coverage for this bug in flush.test.
1674+
#
1675+
drop tables if exists t1, t2;
1676+
create table t1 (i int);
1677+
create temporary table t2 (j int);
1678+
handler t1 open;
1679+
lock table t2 read;
1680+
# This commit should not release any MDL locks.
1681+
commit;
1682+
unlock tables;
1683+
# The below statement crashed before the bug fix as it
1684+
# has attempted to release metadata lock which was
1685+
# already released by commit.
1686+
handler t1 close;
1687+
drop tables t1, t2;

mysql-test/r/handler_myisam.result

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,24 @@ handler t1 close;
16641664
drop function f1;
16651665
drop tables t1, t2;
16661666
#
1667+
# Test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY +
1668+
# HANDLER + LOCK + SP".
1669+
# Also see additional coverage for this bug in flush.test.
1670+
#
1671+
drop tables if exists t1, t2;
1672+
create table t1 (i int);
1673+
create temporary table t2 (j int);
1674+
handler t1 open;
1675+
lock table t2 read;
1676+
# This commit should not release any MDL locks.
1677+
commit;
1678+
unlock tables;
1679+
# The below statement crashed before the bug fix as it
1680+
# has attempted to release metadata lock which was
1681+
# already released by commit.
1682+
handler t1 close;
1683+
drop tables t1, t2;
1684+
#
16671685
# BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash
16681686
#
16691687
CREATE TABLE t1 AS SELECT 1 AS f1;

mysql-test/r/lock_multi.result

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,29 @@ UNLOCK TABLES;
436436
# Reaping: DROP TABLE t1, t2
437437
# Connection default
438438
# Cleanup
439+
#
440+
# Test for bug #51134 "Crash in MDL_lock::destroy on a concurrent
441+
# DDL workload".
442+
#
443+
drop tables if exists t1, t2, t3;
444+
create table t3 (i int);
445+
# Switching to connection 'con1'
446+
# Lock 't3' so upcoming RENAME is blocked.
447+
lock table t3 read;
448+
# Switching to connection 'con2'
449+
# Remember ID for this connection.
450+
# Start statement which will try to acquire two instances
451+
# of X metadata lock on the same object.
452+
# Sending:
453+
rename tables t1 to t2, t2 to t3;;
454+
# Switching to connection 'default'
455+
# Wait until RENAME TABLE is blocked on table 't3'.
456+
# Kill RENAME TABLE.
457+
kill query ID;
458+
# Switching to connection 'con2'
459+
# RENAME TABLE should be aborted but should not crash.
460+
ERROR 70100: Query execution was interrupted
461+
# Switching to connection 'con1'
462+
unlock tables;
463+
# Switching to connection 'default'
464+
drop table t3;

mysql-test/t/flush.test

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,24 @@ set global general_log= @old_general_log;
203203
set global read_only= @old_read_only;
204204

205205
--echo End of 5.1 tests
206+
207+
208+
--echo #
209+
--echo # Additional test for bug #51136 "Crash in pthread_rwlock_rdlock
210+
--echo # on TEMPORARY + HANDLER + LOCK + SP".
211+
--echo # Also see the main test for this bug in include/handler.inc.
212+
--echo #
213+
--disable_warnings
214+
drop tables if exists t1, t2;
215+
--enable_warnings
216+
create table t1 (i int);
217+
create temporary table t2 (j int);
218+
flush tables with read lock;
219+
lock table t2 read;
220+
--echo # This commit should not release any MDL locks.
221+
commit;
222+
--echo # The below statement crashed before the bug fix as it
223+
--echo # has attempted to release global shared metadata lock
224+
--echo # which was already released by commit.
225+
unlock tables;
226+
drop tables t1, t2;

mysql-test/t/lock_multi.test

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,5 +1038,59 @@ disconnect con2;
10381038
disconnect con3;
10391039

10401040

1041+
--echo #
1042+
--echo # Test for bug #51134 "Crash in MDL_lock::destroy on a concurrent
1043+
--echo # DDL workload".
1044+
--echo #
1045+
--disable_warnings
1046+
drop tables if exists t1, t2, t3;
1047+
--enable_warnings
1048+
connect (con1, localhost, root, , );
1049+
connect (con2, localhost, root, , );
1050+
connection default;
1051+
create table t3 (i int);
1052+
1053+
--echo # Switching to connection 'con1'
1054+
connection con1;
1055+
--echo # Lock 't3' so upcoming RENAME is blocked.
1056+
lock table t3 read;
1057+
1058+
--echo # Switching to connection 'con2'
1059+
connection con2;
1060+
--echo # Remember ID for this connection.
1061+
let $ID= `select connection_id()`;
1062+
--echo # Start statement which will try to acquire two instances
1063+
--echo # of X metadata lock on the same object.
1064+
--echo # Sending:
1065+
--send rename tables t1 to t2, t2 to t3;
1066+
1067+
--echo # Switching to connection 'default'
1068+
connection default;
1069+
--echo # Wait until RENAME TABLE is blocked on table 't3'.
1070+
let $wait_condition=
1071+
select count(*) = 1 from information_schema.processlist
1072+
where state = "Waiting for table" and info = "rename tables t1 to t2, t2 to t3";
1073+
--source include/wait_condition.inc
1074+
--echo # Kill RENAME TABLE.
1075+
--replace_result $ID ID
1076+
eval kill query $ID;
1077+
1078+
--echo # Switching to connection 'con2'
1079+
connection con2;
1080+
--echo # RENAME TABLE should be aborted but should not crash.
1081+
--error ER_QUERY_INTERRUPTED
1082+
--reap
1083+
1084+
--echo # Switching to connection 'con1'
1085+
connection con1;
1086+
unlock tables;
1087+
1088+
--echo # Switching to connection 'default'
1089+
connection default;
1090+
disconnect con1;
1091+
disconnect con2;
1092+
drop table t3;
1093+
1094+
10411095
# Wait till all disconnects are completed
10421096
--source include/wait_until_count_sessions.inc

sql/mdl.cc

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,6 +1532,7 @@ bool MDL_context::acquire_locks(MDL_request_list *mdl_requests,
15321532
{
15331533
MDL_request_list::Iterator it(*mdl_requests);
15341534
MDL_request **sort_buf, **p_req;
1535+
MDL_ticket *mdl_svp= mdl_savepoint();
15351536
ssize_t req_count= static_cast<ssize_t>(mdl_requests->elements());
15361537

15371538
if (req_count == 0)
@@ -1565,12 +1566,16 @@ bool MDL_context::acquire_locks(MDL_request_list *mdl_requests,
15651566
return FALSE;
15661567

15671568
err:
1568-
/* Release locks we have managed to acquire so far. */
1569+
/*
1570+
Release locks we have managed to acquire so far.
1571+
Use rollback_to_savepoint() since there may be duplicate
1572+
requests that got assigned the same ticket.
1573+
*/
1574+
rollback_to_savepoint(mdl_svp);
1575+
/* Reset lock requests back to its initial state. */
15691576
for (req_count= p_req - sort_buf, p_req= sort_buf;
15701577
p_req < sort_buf + req_count; p_req++)
15711578
{
1572-
release_lock((*p_req)->ticket);
1573-
/* Reset lock request back to its initial state. */
15741579
(*p_req)->ticket= NULL;
15751580
}
15761581
my_free(sort_buf, MYF(0));

sql/mdl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ class MDL_context
501501

502502
void set_trans_sentinel()
503503
{
504-
m_trans_sentinel= mdl_savepoint();
504+
m_trans_sentinel= m_tickets.front();
505505
}
506506
MDL_ticket *trans_sentinel() const { return m_trans_sentinel; }
507507

0 commit comments

Comments
 (0)