Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
5.5.39
-
None
Description
Deadlock chain:
wrlock(LOCK_grant) -> lock(acl_cache->lock) GRANT/REVOKE CREATE/DROP USER
|
lock(LOCK_open) -> rdlock(LOCK_grant) SELECT * FROM INFORMATION_SCHEMA.COLUMNS
|
wrlock(LOCK_logger) -> lock(LOCK_open) SET @@global.slow_query_log='ON'
|
lock(acl_cache->lock) -> rdlock(LOCK_logger) Failed connection
|
MTR test to reproduce this deadlock:
--source include/have_plugin_auth.inc
|
--source include/have_debug_sync.inc
|
|
SET @@global.slow_query_log='OFF';
|
CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest';
|
CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd';
|
GRANT PROXY ON plug_dest TO plug_user;
|
RENAME USER plug_dest TO new_dest;
|
|
connect(con1, localhost, root,,);
|
connect(con2, localhost, root,,);
|
connect(con3, localhost, root,,);
|
|
connection con1;
|
SET debug_sync='mysql_grant SIGNAL ready1 WAIT_FOR go1';
|
SET debug_dbug='+d,mysql_grant';
|
send REVOKE ALL ON *.* FROM no_such_user@localhost;
|
|
connection con2;
|
SET debug_sync='now WAIT_FOR ready1';
|
SET debug_sync='fill_schema_table_from_frm SIGNAL ready2 WAIT_FOR go2';
|
send SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS;
|
|
connection con3;
|
SET debug_sync='now WAIT_FOR ready2';
|
SET debug_sync='activate_log_handler SIGNAL ready3 WAIT_FOR go3';
|
SET debug_dbug='+d,activate_log_handler';
|
send SET @@global.slow_query_log='ON';
|
|
connection default;
|
SET debug_sync='now WAIT_FOR ready3';
|
--error 1
|
--exec $MYSQL -S $MASTER_MYSOCK -u plug_user --password=plug_dest -e "SELECT 1;"
|
|
connection con1;
|
--error 1141
|
reap;
|
disconnect con1;
|
|
connection con2;
|
reap;
|
disconnect con2;
|
|
connection con3;
|
reap;
|
disconnect con3;
|
|
connection default;
|
DROP USER plug_user, new_dest;
|
SET debug_sync='RESET';
|
Debug sync points:
=== modified file 'sql/log.cc'
|
--- sql/log.cc 2014-08-02 19:26:16 +0000
|
+++ sql/log.cc 2014-09-18 15:16:51 +0000
|
@@ -1400,7 +1400,12 @@ bool LOGGER::activate_log_handler(THD* t
|
{
|
MYSQL_QUERY_LOG *file_log;
|
bool res= FALSE;
|
+ DEBUG_SYNC(thd, "activate_log_handler");
|
lock_exclusive();
|
+ DBUG_EXECUTE_IF("activate_log_handler",
|
+ {
|
+ debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready3"));
|
+ };);
|
switch (log_type) {
|
case QUERY_LOG_SLOW:
|
if (!opt_slow_log)
|
|
=== modified file 'sql/sql_acl.cc'
|
--- sql/sql_acl.cc 2014-08-02 19:26:16 +0000
|
+++ sql/sql_acl.cc 2014-09-18 15:18:52 +0000
|
@@ -53,6 +53,7 @@
|
#include "sql_array.h"
|
|
#include "sql_plugin_compat.h"
|
+#include "debug_sync.h"
|
|
bool mysql_user_table_is_in_short_password_format= false;
|
|
@@ -4142,8 +4143,13 @@ bool mysql_grant(THD *thd, const char *d
|
if (!revoke_grant)
|
create_new_users= test_if_create_new_users(thd);
|
|
+ DEBUG_SYNC(thd, "mysql_grant");
|
/* go through users in user_list */
|
mysql_rwlock_wrlock(&LOCK_grant);
|
+ DBUG_EXECUTE_IF("mysql_grant",
|
+ {
|
+ debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready1"));
|
+ };);
|
mysql_mutex_lock(&acl_cache->lock);
|
grant_version++;
|
|
@@ -9225,7 +9231,12 @@ bool acl_authenticate(THD *thd, uint con
|
if (!acl_proxy_user)
|
{
|
if (!thd->is_error())
|
+ {
|
+ debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go1 WAIT_FOR ready1"));
|
+ debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go2"));
|
+ debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go3 WAIT_FOR ready3"));
|
login_failed_error(thd);
|
+ }
|
mysql_mutex_unlock(&acl_cache->lock);
|
DBUG_RETURN(1);
|
}
|
|
=== modified file 'sql/sql_show.cc'
|
--- sql/sql_show.cc 2014-08-31 17:55:11 +0000
|
+++ sql/sql_show.cc 2014-09-18 15:07:47 +0000
|
@@ -4244,6 +4244,7 @@ static int fill_schema_table_from_frm(TH
|
key_length= create_table_def_key(thd, key, &table_list, 0);
|
hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length);
|
mysql_mutex_lock(&LOCK_open);
|
+ DEBUG_SYNC(thd, "fill_schema_table_from_frm");
|
share= get_table_share(thd, &table_list, key,
|
key_length, OPEN_VIEW, ¬_used, hash_value);
|
if (!share)
|
Attachments
Issue Links
- is part of
-
MDEV-5089 possible deadlocks between rwlocks and mutexes
-
- Closed
-
Activity
Description |
Note: this deadlock wasn't actually reproduced yet. Should affect 5.5 only. Preparation: {noformat} CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; {noformat} Test: {noformat} thread1: REVOKE ALL ON *.* FROM no_such_user@localhost thread2: SELECT * FROM INFORMATION_SCHEMA.COLUMNS thread3: SET @@global.general_log='ON'; SET @@global.general_log='OFF'; thread4: connect as 'plug_user' with password 'plug_dest' (connection must fail) {noformat} Deadlock chain: {noformat} wrlock(LOCK_grant) -> lock(acl_cache->lock) GRANT/REVOKE CREATE/DROP USER lock(LOCK_open) -> rdlock(LOCK_grant) SELECT * FROM INFORMATION_SCHEMA.COLUMNS wrlock(LOCK_logger) -> lock(LOCK_open) SET GLOBAL general_log='ON' lock(acl_cache->lock) -> rdlock(LOCK_logger) Failed connection {noformat} |
Preparation: {noformat} CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; {noformat} Test: {noformat} thread1: REVOKE ALL ON *.* FROM no_such_user@localhost thread2: SELECT * FROM INFORMATION_SCHEMA.COLUMNS thread3: SET @@global.general_log='ON'; SET @@global.general_log='OFF'; thread4: connect as 'plug_user' with password 'plug_dest' (connection must fail) {noformat} Deadlock chain: {noformat} wrlock(LOCK_grant) -> lock(acl_cache->lock) GRANT/REVOKE CREATE/DROP USER lock(LOCK_open) -> rdlock(LOCK_grant) SELECT * FROM INFORMATION_SCHEMA.COLUMNS wrlock(LOCK_logger) -> lock(LOCK_open) SET GLOBAL general_log='ON' lock(acl_cache->lock) -> rdlock(LOCK_logger) Failed connection {noformat} MTR test to reproduce this deadlock: {noformat} --source include/have_plugin_auth.inc --source include/have_debug_sync.inc SET @@global.slow_query_log='OFF'; CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; connect(con1, localhost, root,,); connect(con2, localhost, root,,); connect(con3, localhost, root,,); connection con1; SET debug_sync='mysql_grant SIGNAL ready1 WAIT_FOR go1'; SET @@global.debug_dbug='+d,mysql_grant'; send REVOKE ALL ON *.* FROM no_such_user@localhost; connection con2; SET debug_sync='now WAIT_FOR ready1'; SET debug_sync='fill_schema_table_from_frm SIGNAL ready2 WAIT_FOR go2 EXECUTE 1'; send SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS; connection con3; SET debug_sync='now WAIT_FOR ready2'; SET debug_sync='activate_log_handler SIGNAL ready3 WAIT_FOR go3'; SET @@global.debug_dbug='+d,activate_log_handler'; send SET @@global.slow_query_log='ON'; connection default; SET debug_sync='now WAIT_FOR ready3'; --error 1 --exec $MYSQL -S $MASTER_MYSOCK -u plug_user --password=plug_dest -e "SELECT 1;" connection con1; reap; disconnect con1; connection con2; --error 1141 reap; disconnect con2; connection con3; reap; disconnect con3; connection default; DROP USER plug_user,new_dest; {noformat} Debug sync points: {noformat} === modified file 'sql/log.cc' --- sql/log.cc 2014-08-02 19:26:16 +0000 +++ sql/log.cc 2014-09-18 10:20:44 +0000 @@ -1400,7 +1400,12 @@ bool LOGGER::activate_log_handler(THD* t { MYSQL_QUERY_LOG *file_log; bool res= FALSE; + DEBUG_SYNC(thd, "activate_log_handler"); lock_exclusive(); + DBUG_EXECUTE_IF("activate_log_handler", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready3 WAIT_FOR go3")); + };); switch (log_type) { case QUERY_LOG_SLOW: if (!opt_slow_log) === modified file 'sql/sql_acl.cc' --- sql/sql_acl.cc 2014-08-02 19:26:16 +0000 +++ sql/sql_acl.cc 2014-09-18 11:43:48 +0000 @@ -53,6 +53,7 @@ #include "sql_array.h" #include "sql_plugin_compat.h" +#include "debug_sync.h" bool mysql_user_table_is_in_short_password_format= false; @@ -4142,8 +4143,13 @@ bool mysql_grant(THD *thd, const char *d if (!revoke_grant) create_new_users= test_if_create_new_users(thd); + DEBUG_SYNC(thd, "mysql_grant"); /* go through users in user_list */ mysql_rwlock_wrlock(&LOCK_grant); + DBUG_EXECUTE_IF("mysql_grant", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready1 WAIT_FOR go1")); + };); mysql_mutex_lock(&acl_cache->lock); grant_version++; @@ -9225,7 +9231,14 @@ bool acl_authenticate(THD *thd, uint con if (!acl_proxy_user) { if (!thd->is_error()) + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go1 WAIT_FOR ready1")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go3 WAIT_FOR ready3")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go1")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go2")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go3")); login_failed_error(thd); + } mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(1); } === modified file 'sql/sql_show.cc' --- sql/sql_show.cc 2014-08-31 17:55:11 +0000 +++ sql/sql_show.cc 2014-09-18 09:45:12 +0000 @@ -4244,6 +4244,7 @@ static int fill_schema_table_from_frm(TH key_length= create_table_def_key(thd, key, &table_list, 0); hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); mysql_mutex_lock(&LOCK_open); + DEBUG_SYNC(thd, "fill_schema_table_from_frm"); share= get_table_share(thd, &table_list, key, key_length, OPEN_VIEW, ¬_used, hash_value); if (!share) {noformat} |
Description |
Preparation: {noformat} CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; {noformat} Test: {noformat} thread1: REVOKE ALL ON *.* FROM no_such_user@localhost thread2: SELECT * FROM INFORMATION_SCHEMA.COLUMNS thread3: SET @@global.general_log='ON'; SET @@global.general_log='OFF'; thread4: connect as 'plug_user' with password 'plug_dest' (connection must fail) {noformat} Deadlock chain: {noformat} wrlock(LOCK_grant) -> lock(acl_cache->lock) GRANT/REVOKE CREATE/DROP USER lock(LOCK_open) -> rdlock(LOCK_grant) SELECT * FROM INFORMATION_SCHEMA.COLUMNS wrlock(LOCK_logger) -> lock(LOCK_open) SET GLOBAL general_log='ON' lock(acl_cache->lock) -> rdlock(LOCK_logger) Failed connection {noformat} MTR test to reproduce this deadlock: {noformat} --source include/have_plugin_auth.inc --source include/have_debug_sync.inc SET @@global.slow_query_log='OFF'; CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; connect(con1, localhost, root,,); connect(con2, localhost, root,,); connect(con3, localhost, root,,); connection con1; SET debug_sync='mysql_grant SIGNAL ready1 WAIT_FOR go1'; SET @@global.debug_dbug='+d,mysql_grant'; send REVOKE ALL ON *.* FROM no_such_user@localhost; connection con2; SET debug_sync='now WAIT_FOR ready1'; SET debug_sync='fill_schema_table_from_frm SIGNAL ready2 WAIT_FOR go2 EXECUTE 1'; send SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS; connection con3; SET debug_sync='now WAIT_FOR ready2'; SET debug_sync='activate_log_handler SIGNAL ready3 WAIT_FOR go3'; SET @@global.debug_dbug='+d,activate_log_handler'; send SET @@global.slow_query_log='ON'; connection default; SET debug_sync='now WAIT_FOR ready3'; --error 1 --exec $MYSQL -S $MASTER_MYSOCK -u plug_user --password=plug_dest -e "SELECT 1;" connection con1; reap; disconnect con1; connection con2; --error 1141 reap; disconnect con2; connection con3; reap; disconnect con3; connection default; DROP USER plug_user,new_dest; {noformat} Debug sync points: {noformat} === modified file 'sql/log.cc' --- sql/log.cc 2014-08-02 19:26:16 +0000 +++ sql/log.cc 2014-09-18 10:20:44 +0000 @@ -1400,7 +1400,12 @@ bool LOGGER::activate_log_handler(THD* t { MYSQL_QUERY_LOG *file_log; bool res= FALSE; + DEBUG_SYNC(thd, "activate_log_handler"); lock_exclusive(); + DBUG_EXECUTE_IF("activate_log_handler", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready3 WAIT_FOR go3")); + };); switch (log_type) { case QUERY_LOG_SLOW: if (!opt_slow_log) === modified file 'sql/sql_acl.cc' --- sql/sql_acl.cc 2014-08-02 19:26:16 +0000 +++ sql/sql_acl.cc 2014-09-18 11:43:48 +0000 @@ -53,6 +53,7 @@ #include "sql_array.h" #include "sql_plugin_compat.h" +#include "debug_sync.h" bool mysql_user_table_is_in_short_password_format= false; @@ -4142,8 +4143,13 @@ bool mysql_grant(THD *thd, const char *d if (!revoke_grant) create_new_users= test_if_create_new_users(thd); + DEBUG_SYNC(thd, "mysql_grant"); /* go through users in user_list */ mysql_rwlock_wrlock(&LOCK_grant); + DBUG_EXECUTE_IF("mysql_grant", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready1 WAIT_FOR go1")); + };); mysql_mutex_lock(&acl_cache->lock); grant_version++; @@ -9225,7 +9231,14 @@ bool acl_authenticate(THD *thd, uint con if (!acl_proxy_user) { if (!thd->is_error()) + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go1 WAIT_FOR ready1")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go3 WAIT_FOR ready3")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go1")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go2")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go3")); login_failed_error(thd); + } mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(1); } === modified file 'sql/sql_show.cc' --- sql/sql_show.cc 2014-08-31 17:55:11 +0000 +++ sql/sql_show.cc 2014-09-18 09:45:12 +0000 @@ -4244,6 +4244,7 @@ static int fill_schema_table_from_frm(TH key_length= create_table_def_key(thd, key, &table_list, 0); hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); mysql_mutex_lock(&LOCK_open); + DEBUG_SYNC(thd, "fill_schema_table_from_frm"); share= get_table_share(thd, &table_list, key, key_length, OPEN_VIEW, ¬_used, hash_value); if (!share) {noformat} |
Preparation: {noformat} CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; {noformat} Test: {noformat} thread1: REVOKE ALL ON *.* FROM no_such_user@localhost thread2: SELECT * FROM INFORMATION_SCHEMA.COLUMNS thread3: SET @@global.general_log='ON'; SET @@global.general_log='OFF'; thread4: connect as 'plug_user' with password 'plug_dest' (connection must fail) {noformat} Deadlock chain: {noformat} wrlock(LOCK_grant) -> lock(acl_cache->lock) GRANT/REVOKE CREATE/DROP USER lock(LOCK_open) -> rdlock(LOCK_grant) SELECT * FROM INFORMATION_SCHEMA.COLUMNS wrlock(LOCK_logger) -> lock(LOCK_open) SET GLOBAL general_log='ON' lock(acl_cache->lock) -> rdlock(LOCK_logger) Failed connection {noformat} MTR test to reproduce this deadlock: {noformat} --source include/have_plugin_auth.inc --source include/have_debug_sync.inc SET @@global.slow_query_log='OFF'; CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; connect(con1, localhost, root,,); connect(con2, localhost, root,,); connect(con3, localhost, root,,); connection con1; SET debug_sync='mysql_grant SIGNAL ready1 WAIT_FOR go1'; SET debug_dbug='+d,mysql_grant'; send REVOKE ALL ON *.* FROM no_such_user@localhost; connection con2; SET debug_sync='now WAIT_FOR ready1'; SET debug_sync='fill_schema_table_from_frm SIGNAL ready2 WAIT_FOR go2'; send SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS; connection con3; SET debug_sync='now WAIT_FOR ready2'; SET debug_sync='activate_log_handler SIGNAL ready3 WAIT_FOR go3'; SET debug_dbug='+d,activate_log_handler'; send SET @@global.slow_query_log='ON'; connection default; SET debug_sync='now WAIT_FOR ready3'; --error 1 --exec $MYSQL -S $MASTER_MYSOCK -u plug_user --password=plug_dest -e "SELECT 1;" connection con1; --error 1141 reap; disconnect con1; connection con2; reap; disconnect con2; connection con3; reap; disconnect con3; connection default; DROP USER plug_user, new_dest; SET debug_sync='RESET'; {noformat} Debug sync points: {noformat} === modified file 'sql/log.cc' --- sql/log.cc 2014-08-02 19:26:16 +0000 +++ sql/log.cc 2014-09-18 15:16:51 +0000 @@ -1400,7 +1400,12 @@ bool LOGGER::activate_log_handler(THD* t { MYSQL_QUERY_LOG *file_log; bool res= FALSE; + DEBUG_SYNC(thd, "activate_log_handler"); lock_exclusive(); + DBUG_EXECUTE_IF("activate_log_handler", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready3")); + };); switch (log_type) { case QUERY_LOG_SLOW: if (!opt_slow_log) === modified file 'sql/sql_acl.cc' --- sql/sql_acl.cc 2014-08-02 19:26:16 +0000 +++ sql/sql_acl.cc 2014-09-18 15:18:52 +0000 @@ -53,6 +53,7 @@ #include "sql_array.h" #include "sql_plugin_compat.h" +#include "debug_sync.h" bool mysql_user_table_is_in_short_password_format= false; @@ -4142,8 +4143,13 @@ bool mysql_grant(THD *thd, const char *d if (!revoke_grant) create_new_users= test_if_create_new_users(thd); + DEBUG_SYNC(thd, "mysql_grant"); /* go through users in user_list */ mysql_rwlock_wrlock(&LOCK_grant); + DBUG_EXECUTE_IF("mysql_grant", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready1")); + };); mysql_mutex_lock(&acl_cache->lock); grant_version++; @@ -9225,7 +9231,12 @@ bool acl_authenticate(THD *thd, uint con if (!acl_proxy_user) { if (!thd->is_error()) + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go1 WAIT_FOR ready1")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go2")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go3 WAIT_FOR ready3")); login_failed_error(thd); + } mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(1); } === modified file 'sql/sql_show.cc' --- sql/sql_show.cc 2014-08-31 17:55:11 +0000 +++ sql/sql_show.cc 2014-09-18 15:07:47 +0000 @@ -4244,6 +4244,7 @@ static int fill_schema_table_from_frm(TH key_length= create_table_def_key(thd, key, &table_list, 0); hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); mysql_mutex_lock(&LOCK_open); + DEBUG_SYNC(thd, "fill_schema_table_from_frm"); share= get_table_share(thd, &table_list, key, key_length, OPEN_VIEW, ¬_used, hash_value); if (!share) {noformat} |
Description |
Preparation: {noformat} CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; {noformat} Test: {noformat} thread1: REVOKE ALL ON *.* FROM no_such_user@localhost thread2: SELECT * FROM INFORMATION_SCHEMA.COLUMNS thread3: SET @@global.general_log='ON'; SET @@global.general_log='OFF'; thread4: connect as 'plug_user' with password 'plug_dest' (connection must fail) {noformat} Deadlock chain: {noformat} wrlock(LOCK_grant) -> lock(acl_cache->lock) GRANT/REVOKE CREATE/DROP USER lock(LOCK_open) -> rdlock(LOCK_grant) SELECT * FROM INFORMATION_SCHEMA.COLUMNS wrlock(LOCK_logger) -> lock(LOCK_open) SET GLOBAL general_log='ON' lock(acl_cache->lock) -> rdlock(LOCK_logger) Failed connection {noformat} MTR test to reproduce this deadlock: {noformat} --source include/have_plugin_auth.inc --source include/have_debug_sync.inc SET @@global.slow_query_log='OFF'; CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; connect(con1, localhost, root,,); connect(con2, localhost, root,,); connect(con3, localhost, root,,); connection con1; SET debug_sync='mysql_grant SIGNAL ready1 WAIT_FOR go1'; SET debug_dbug='+d,mysql_grant'; send REVOKE ALL ON *.* FROM no_such_user@localhost; connection con2; SET debug_sync='now WAIT_FOR ready1'; SET debug_sync='fill_schema_table_from_frm SIGNAL ready2 WAIT_FOR go2'; send SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS; connection con3; SET debug_sync='now WAIT_FOR ready2'; SET debug_sync='activate_log_handler SIGNAL ready3 WAIT_FOR go3'; SET debug_dbug='+d,activate_log_handler'; send SET @@global.slow_query_log='ON'; connection default; SET debug_sync='now WAIT_FOR ready3'; --error 1 --exec $MYSQL -S $MASTER_MYSOCK -u plug_user --password=plug_dest -e "SELECT 1;" connection con1; --error 1141 reap; disconnect con1; connection con2; reap; disconnect con2; connection con3; reap; disconnect con3; connection default; DROP USER plug_user, new_dest; SET debug_sync='RESET'; {noformat} Debug sync points: {noformat} === modified file 'sql/log.cc' --- sql/log.cc 2014-08-02 19:26:16 +0000 +++ sql/log.cc 2014-09-18 15:16:51 +0000 @@ -1400,7 +1400,12 @@ bool LOGGER::activate_log_handler(THD* t { MYSQL_QUERY_LOG *file_log; bool res= FALSE; + DEBUG_SYNC(thd, "activate_log_handler"); lock_exclusive(); + DBUG_EXECUTE_IF("activate_log_handler", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready3")); + };); switch (log_type) { case QUERY_LOG_SLOW: if (!opt_slow_log) === modified file 'sql/sql_acl.cc' --- sql/sql_acl.cc 2014-08-02 19:26:16 +0000 +++ sql/sql_acl.cc 2014-09-18 15:18:52 +0000 @@ -53,6 +53,7 @@ #include "sql_array.h" #include "sql_plugin_compat.h" +#include "debug_sync.h" bool mysql_user_table_is_in_short_password_format= false; @@ -4142,8 +4143,13 @@ bool mysql_grant(THD *thd, const char *d if (!revoke_grant) create_new_users= test_if_create_new_users(thd); + DEBUG_SYNC(thd, "mysql_grant"); /* go through users in user_list */ mysql_rwlock_wrlock(&LOCK_grant); + DBUG_EXECUTE_IF("mysql_grant", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready1")); + };); mysql_mutex_lock(&acl_cache->lock); grant_version++; @@ -9225,7 +9231,12 @@ bool acl_authenticate(THD *thd, uint con if (!acl_proxy_user) { if (!thd->is_error()) + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go1 WAIT_FOR ready1")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go2")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go3 WAIT_FOR ready3")); login_failed_error(thd); + } mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(1); } === modified file 'sql/sql_show.cc' --- sql/sql_show.cc 2014-08-31 17:55:11 +0000 +++ sql/sql_show.cc 2014-09-18 15:07:47 +0000 @@ -4244,6 +4244,7 @@ static int fill_schema_table_from_frm(TH key_length= create_table_def_key(thd, key, &table_list, 0); hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); mysql_mutex_lock(&LOCK_open); + DEBUG_SYNC(thd, "fill_schema_table_from_frm"); share= get_table_share(thd, &table_list, key, key_length, OPEN_VIEW, ¬_used, hash_value); if (!share) {noformat} |
Deadlock chain: {noformat} wrlock(LOCK_grant) -> lock(acl_cache->lock) GRANT/REVOKE CREATE/DROP USER lock(LOCK_open) -> rdlock(LOCK_grant) SELECT * FROM INFORMATION_SCHEMA.COLUMNS wrlock(LOCK_logger) -> lock(LOCK_open) SET @@global.slow_query_log='ON'; lock(acl_cache->lock) -> rdlock(LOCK_logger) Failed connection {noformat} MTR test to reproduce this deadlock: {noformat} --source include/have_plugin_auth.inc --source include/have_debug_sync.inc SET @@global.slow_query_log='OFF'; CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; connect(con1, localhost, root,,); connect(con2, localhost, root,,); connect(con3, localhost, root,,); connection con1; SET debug_sync='mysql_grant SIGNAL ready1 WAIT_FOR go1'; SET debug_dbug='+d,mysql_grant'; send REVOKE ALL ON *.* FROM no_such_user@localhost; connection con2; SET debug_sync='now WAIT_FOR ready1'; SET debug_sync='fill_schema_table_from_frm SIGNAL ready2 WAIT_FOR go2'; send SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS; connection con3; SET debug_sync='now WAIT_FOR ready2'; SET debug_sync='activate_log_handler SIGNAL ready3 WAIT_FOR go3'; SET debug_dbug='+d,activate_log_handler'; send SET @@global.slow_query_log='ON'; connection default; SET debug_sync='now WAIT_FOR ready3'; --error 1 --exec $MYSQL -S $MASTER_MYSOCK -u plug_user --password=plug_dest -e "SELECT 1;" connection con1; --error 1141 reap; disconnect con1; connection con2; reap; disconnect con2; connection con3; reap; disconnect con3; connection default; DROP USER plug_user, new_dest; SET debug_sync='RESET'; {noformat} Debug sync points: {noformat} === modified file 'sql/log.cc' --- sql/log.cc 2014-08-02 19:26:16 +0000 +++ sql/log.cc 2014-09-18 15:16:51 +0000 @@ -1400,7 +1400,12 @@ bool LOGGER::activate_log_handler(THD* t { MYSQL_QUERY_LOG *file_log; bool res= FALSE; + DEBUG_SYNC(thd, "activate_log_handler"); lock_exclusive(); + DBUG_EXECUTE_IF("activate_log_handler", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready3")); + };); switch (log_type) { case QUERY_LOG_SLOW: if (!opt_slow_log) === modified file 'sql/sql_acl.cc' --- sql/sql_acl.cc 2014-08-02 19:26:16 +0000 +++ sql/sql_acl.cc 2014-09-18 15:18:52 +0000 @@ -53,6 +53,7 @@ #include "sql_array.h" #include "sql_plugin_compat.h" +#include "debug_sync.h" bool mysql_user_table_is_in_short_password_format= false; @@ -4142,8 +4143,13 @@ bool mysql_grant(THD *thd, const char *d if (!revoke_grant) create_new_users= test_if_create_new_users(thd); + DEBUG_SYNC(thd, "mysql_grant"); /* go through users in user_list */ mysql_rwlock_wrlock(&LOCK_grant); + DBUG_EXECUTE_IF("mysql_grant", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready1")); + };); mysql_mutex_lock(&acl_cache->lock); grant_version++; @@ -9225,7 +9231,12 @@ bool acl_authenticate(THD *thd, uint con if (!acl_proxy_user) { if (!thd->is_error()) + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go1 WAIT_FOR ready1")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go2")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go3 WAIT_FOR ready3")); login_failed_error(thd); + } mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(1); } === modified file 'sql/sql_show.cc' --- sql/sql_show.cc 2014-08-31 17:55:11 +0000 +++ sql/sql_show.cc 2014-09-18 15:07:47 +0000 @@ -4244,6 +4244,7 @@ static int fill_schema_table_from_frm(TH key_length= create_table_def_key(thd, key, &table_list, 0); hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); mysql_mutex_lock(&LOCK_open); + DEBUG_SYNC(thd, "fill_schema_table_from_frm"); share= get_table_share(thd, &table_list, key, key_length, OPEN_VIEW, ¬_used, hash_value); if (!share) {noformat} |
Description |
Deadlock chain: {noformat} wrlock(LOCK_grant) -> lock(acl_cache->lock) GRANT/REVOKE CREATE/DROP USER lock(LOCK_open) -> rdlock(LOCK_grant) SELECT * FROM INFORMATION_SCHEMA.COLUMNS wrlock(LOCK_logger) -> lock(LOCK_open) SET @@global.slow_query_log='ON'; lock(acl_cache->lock) -> rdlock(LOCK_logger) Failed connection {noformat} MTR test to reproduce this deadlock: {noformat} --source include/have_plugin_auth.inc --source include/have_debug_sync.inc SET @@global.slow_query_log='OFF'; CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; connect(con1, localhost, root,,); connect(con2, localhost, root,,); connect(con3, localhost, root,,); connection con1; SET debug_sync='mysql_grant SIGNAL ready1 WAIT_FOR go1'; SET debug_dbug='+d,mysql_grant'; send REVOKE ALL ON *.* FROM no_such_user@localhost; connection con2; SET debug_sync='now WAIT_FOR ready1'; SET debug_sync='fill_schema_table_from_frm SIGNAL ready2 WAIT_FOR go2'; send SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS; connection con3; SET debug_sync='now WAIT_FOR ready2'; SET debug_sync='activate_log_handler SIGNAL ready3 WAIT_FOR go3'; SET debug_dbug='+d,activate_log_handler'; send SET @@global.slow_query_log='ON'; connection default; SET debug_sync='now WAIT_FOR ready3'; --error 1 --exec $MYSQL -S $MASTER_MYSOCK -u plug_user --password=plug_dest -e "SELECT 1;" connection con1; --error 1141 reap; disconnect con1; connection con2; reap; disconnect con2; connection con3; reap; disconnect con3; connection default; DROP USER plug_user, new_dest; SET debug_sync='RESET'; {noformat} Debug sync points: {noformat} === modified file 'sql/log.cc' --- sql/log.cc 2014-08-02 19:26:16 +0000 +++ sql/log.cc 2014-09-18 15:16:51 +0000 @@ -1400,7 +1400,12 @@ bool LOGGER::activate_log_handler(THD* t { MYSQL_QUERY_LOG *file_log; bool res= FALSE; + DEBUG_SYNC(thd, "activate_log_handler"); lock_exclusive(); + DBUG_EXECUTE_IF("activate_log_handler", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready3")); + };); switch (log_type) { case QUERY_LOG_SLOW: if (!opt_slow_log) === modified file 'sql/sql_acl.cc' --- sql/sql_acl.cc 2014-08-02 19:26:16 +0000 +++ sql/sql_acl.cc 2014-09-18 15:18:52 +0000 @@ -53,6 +53,7 @@ #include "sql_array.h" #include "sql_plugin_compat.h" +#include "debug_sync.h" bool mysql_user_table_is_in_short_password_format= false; @@ -4142,8 +4143,13 @@ bool mysql_grant(THD *thd, const char *d if (!revoke_grant) create_new_users= test_if_create_new_users(thd); + DEBUG_SYNC(thd, "mysql_grant"); /* go through users in user_list */ mysql_rwlock_wrlock(&LOCK_grant); + DBUG_EXECUTE_IF("mysql_grant", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready1")); + };); mysql_mutex_lock(&acl_cache->lock); grant_version++; @@ -9225,7 +9231,12 @@ bool acl_authenticate(THD *thd, uint con if (!acl_proxy_user) { if (!thd->is_error()) + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go1 WAIT_FOR ready1")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go2")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go3 WAIT_FOR ready3")); login_failed_error(thd); + } mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(1); } === modified file 'sql/sql_show.cc' --- sql/sql_show.cc 2014-08-31 17:55:11 +0000 +++ sql/sql_show.cc 2014-09-18 15:07:47 +0000 @@ -4244,6 +4244,7 @@ static int fill_schema_table_from_frm(TH key_length= create_table_def_key(thd, key, &table_list, 0); hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); mysql_mutex_lock(&LOCK_open); + DEBUG_SYNC(thd, "fill_schema_table_from_frm"); share= get_table_share(thd, &table_list, key, key_length, OPEN_VIEW, ¬_used, hash_value); if (!share) {noformat} |
Deadlock chain: {noformat} wrlock(LOCK_grant) -> lock(acl_cache->lock) GRANT/REVOKE CREATE/DROP USER lock(LOCK_open) -> rdlock(LOCK_grant) SELECT * FROM INFORMATION_SCHEMA.COLUMNS wrlock(LOCK_logger) -> lock(LOCK_open) SET @@global.slow_query_log='ON' lock(acl_cache->lock) -> rdlock(LOCK_logger) Failed connection {noformat} MTR test to reproduce this deadlock: {noformat} --source include/have_plugin_auth.inc --source include/have_debug_sync.inc SET @@global.slow_query_log='OFF'; CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; RENAME USER plug_dest TO new_dest; connect(con1, localhost, root,,); connect(con2, localhost, root,,); connect(con3, localhost, root,,); connection con1; SET debug_sync='mysql_grant SIGNAL ready1 WAIT_FOR go1'; SET debug_dbug='+d,mysql_grant'; send REVOKE ALL ON *.* FROM no_such_user@localhost; connection con2; SET debug_sync='now WAIT_FOR ready1'; SET debug_sync='fill_schema_table_from_frm SIGNAL ready2 WAIT_FOR go2'; send SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS; connection con3; SET debug_sync='now WAIT_FOR ready2'; SET debug_sync='activate_log_handler SIGNAL ready3 WAIT_FOR go3'; SET debug_dbug='+d,activate_log_handler'; send SET @@global.slow_query_log='ON'; connection default; SET debug_sync='now WAIT_FOR ready3'; --error 1 --exec $MYSQL -S $MASTER_MYSOCK -u plug_user --password=plug_dest -e "SELECT 1;" connection con1; --error 1141 reap; disconnect con1; connection con2; reap; disconnect con2; connection con3; reap; disconnect con3; connection default; DROP USER plug_user, new_dest; SET debug_sync='RESET'; {noformat} Debug sync points: {noformat} === modified file 'sql/log.cc' --- sql/log.cc 2014-08-02 19:26:16 +0000 +++ sql/log.cc 2014-09-18 15:16:51 +0000 @@ -1400,7 +1400,12 @@ bool LOGGER::activate_log_handler(THD* t { MYSQL_QUERY_LOG *file_log; bool res= FALSE; + DEBUG_SYNC(thd, "activate_log_handler"); lock_exclusive(); + DBUG_EXECUTE_IF("activate_log_handler", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready3")); + };); switch (log_type) { case QUERY_LOG_SLOW: if (!opt_slow_log) === modified file 'sql/sql_acl.cc' --- sql/sql_acl.cc 2014-08-02 19:26:16 +0000 +++ sql/sql_acl.cc 2014-09-18 15:18:52 +0000 @@ -53,6 +53,7 @@ #include "sql_array.h" #include "sql_plugin_compat.h" +#include "debug_sync.h" bool mysql_user_table_is_in_short_password_format= false; @@ -4142,8 +4143,13 @@ bool mysql_grant(THD *thd, const char *d if (!revoke_grant) create_new_users= test_if_create_new_users(thd); + DEBUG_SYNC(thd, "mysql_grant"); /* go through users in user_list */ mysql_rwlock_wrlock(&LOCK_grant); + DBUG_EXECUTE_IF("mysql_grant", + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL ready1")); + };); mysql_mutex_lock(&acl_cache->lock); grant_version++; @@ -9225,7 +9231,12 @@ bool acl_authenticate(THD *thd, uint con if (!acl_proxy_user) { if (!thd->is_error()) + { + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go1 WAIT_FOR ready1")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go2")); + debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go3 WAIT_FOR ready3")); login_failed_error(thd); + } mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(1); } === modified file 'sql/sql_show.cc' --- sql/sql_show.cc 2014-08-31 17:55:11 +0000 +++ sql/sql_show.cc 2014-09-18 15:07:47 +0000 @@ -4244,6 +4244,7 @@ static int fill_schema_table_from_frm(TH key_length= create_table_def_key(thd, key, &table_list, 0); hash_value= my_calc_hash(&table_def_cache, (uchar*) key, key_length); mysql_mutex_lock(&LOCK_open); + DEBUG_SYNC(thd, "fill_schema_table_from_frm"); share= get_table_share(thd, &table_list, key, key_length, OPEN_VIEW, ¬_used, hash_value); if (!share) {noformat} |
Summary | Deadlock between GRANT/REVOKE, SELECT FROM I_S.COLUMNS, SET general_log and failed connection attempt | Deadlock between GRANT/REVOKE, SELECT FROM I_S.COLUMNS, SET slow_query_log and failed connection attempt |
Assignee | Sergey Vojtovich [ svoj ] | Sergei Golubchik [ serg ] |
Status | Open [ 1 ] | In Review [ 10002 ] |
Assignee | Sergei Golubchik [ serg ] | Sergey Vojtovich [ svoj ] |
Status | In Review [ 10002 ] | Stalled [ 10000 ] |
Component/s | OTHER [ 10125 ] | |
Resolution | Fixed [ 1 ] | |
Status | Stalled [ 10000 ] | Closed [ 6 ] |
Workflow | MariaDB v2 [ 54301 ] | MariaDB v3 [ 63376 ] |
Workflow | MariaDB v3 [ 63376 ] | MariaDB v4 [ 148229 ] |
Sergei, please review fix for this bug. Even though 10.0 is most probably not affect, I'd recommend to have this fix merged: the less relationships between locks - the better.