1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Fix for bug #12423 "Deadlock when doing FLUSH PRIVILEGES and GRANT in

multi-threaded environment".

To avoid deadlocks between several simultaneously run account management 
commands (particularly between FLUSH PRIVILEGES/SET PASSWORD and GRANT
commands) we should always take table and internal locks during their
execution in the same order. In other words we should first open and lock
privilege tables and only then obtain acl_cache::lock/LOCK_grant locks.


mysql-test/r/grant2.result:
  Added test for bug #12423 "Deadlock when doing FLUSH PRIVILEGES and GRANT in 
  multi-threaded environment".
mysql-test/t/grant2.test:
  Added test for bug #12423 "Deadlock when doing FLUSH PRIVILEGES and GRANT in 
  multi-threaded environment".
sql/mysqld.cc:
  acl_init/grant_init() are now used only at server start up so they always
  allocate temporary THD object and don't need argument for passing pointer
  to it.
sql/sql_acl.cc:
  To avoid deadlocks between several simultaneously run account management 
  commands (particularly between FLUSH PRIVILEGES/SET PASSWORD and GRANT
  commands) we should always take table and internal locks during their
  execution in the same order. In other words we should first open and lock
  privilege tables and only then obtain acl_cache::lock/LOCK_grant locks.
  
  Changed acl_reload()/grant_reload() and change_password()/update_user_table()
  in such way that they obey this principle. Now in acl_reload()/grant_reload()/
  change_password() we open and lock privilege tables, then obtain internal
  locks and then call acl_load()/grant_load()/update_user_table() functions to
  do actual loading or updating.
sql/sql_acl.h:
  acl_init/grant_init() are now used only at server start up so they always
  allocate temporary THD object and don't need argument for passing pointer
  to it. acl_reload()/grant_reload() now are able to report about their
  success or failure through return value.
sql/sql_parse.cc:
  If reload_acl_and_cache() is called from SIGHUP handler we have to
  allocate temporary THD for execution of acl_reload()/grant_reload().
This commit is contained in:
unknown
2005-09-01 16:52:59 +04:00
parent 9df32ec8f8
commit 2a64e9a2e8
6 changed files with 320 additions and 171 deletions

View File

@ -96,3 +96,12 @@ i
REVOKE ALL ON mysqltest_1.t1 FROM mysqltest_1@'127.0.0.0/255.0.0.0';
drop table mysqltest_1.t1;
drop database mysqltest_1;
lock table mysql.user write;
flush privileges;
grant all on *.* to 'mysqltest_1'@'localhost';
unlock tables;
lock table mysql.user write;
set password for 'mysqltest_1'@'localhost' = password('');
revoke all on *.* from 'mysqltest_1'@'localhost';
unlock tables;
drop user 'mysqltest_1'@'localhost';

View File

@ -125,4 +125,47 @@ REVOKE ALL ON mysqltest_1.t1 FROM mysqltest_1@'127.0.0.0/255.0.0.0';
drop table mysqltest_1.t1;
drop database mysqltest_1;
# Bug #12423 "Deadlock when doing FLUSH PRIVILEGES and GRANT in
# multi-threaded environment". We should be able to execute FLUSH
# PRIVILEGES and SET PASSWORD simultaneously with other account
# management commands (such as GRANT and REVOKE) without causing
# deadlocks. To achieve this we should ensure that all account
# management commands take table and internal locks in the same order.
connect (con2root,localhost,root,,);
connect (con3root,localhost,root,,);
# Check that we can execute FLUSH PRIVILEGES and GRANT simultaneously
# This will check that locks are taken in proper order during both
# user/db-level and table/column-level privileges reloading.
connection default;
lock table mysql.user write;
connection con2root;
send flush privileges;
connection con3root;
send grant all on *.* to 'mysqltest_1'@'localhost';
connection default;
unlock tables;
connection con2root;
reap;
connection con3root;
reap;
# Check for simultaneous SET PASSWORD and REVOKE.
connection default;
lock table mysql.user write;
connection con2root;
send set password for 'mysqltest_1'@'localhost' = password('');
connection con3root;
send revoke all on *.* from 'mysqltest_1'@'localhost';
connection default;
unlock tables;
connection con2root;
reap;
connection con3root;
reap;
connection default;
# Clean-up
drop user 'mysqltest_1'@'localhost';
disconnect con2root;
disconnect con3root;
# End of 4.1 tests