From fdfb74b38ea81d8cdd2007b469c4239691517b6a Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Mon, 22 Mar 2010 09:51:16 +0000 Subject: [PATCH] BUG#51987: revoke privileges logs wrong error code A failed REVOKE statement is logged with error=0, thus causing the slave to stop. The slave should not stop as this was an expected error. Given that the execution failed on the master as well the error code should be logged so that the slave can replay the statement, get an error and compare with the master's execution outcome. If errors match, then slave can proceed with replication, as the error it got, when replaying the statement, was expected. In this particular case, the bug surfaces because the error code is pushed to the THD diagnostics area after writing the event to the binary log. Therefore, it would be logged with the THD diagnostics area clean, hence its error code would not contain the correct code. We fix this by moving the error reporting ahead of the call to the routine that writes the event to the binary log. --- mysql-test/suite/rpl/r/rpl_do_grant.result | 14 +++++++++++ mysql-test/suite/rpl/t/rpl_do_grant.test | 29 ++++++++++++++++++++++ sql/sql_acl.cc | 10 ++++---- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_do_grant.result b/mysql-test/suite/rpl/r/rpl_do_grant.result index 65c60acc651..4d8cfe3d8b8 100644 --- a/mysql-test/suite/rpl/r/rpl_do_grant.result +++ b/mysql-test/suite/rpl/r/rpl_do_grant.result @@ -242,4 +242,18 @@ GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION DROP TABLE t1; DROP PROCEDURE p1; DROP USER 'user49119'@'localhost'; +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +grant all on *.* to foo@"1.2.3.4"; +revoke all privileges, grant option from "foo"; +ERROR HY000: Can't revoke all privileges for one or more of the requested users +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; grant all on *.* to foo@"1.2.3.4" +master-bin.000001 # Query # # use `test`; revoke all privileges, grant option from "foo" +DROP USER foo@"1.2.3.4"; "End of test" diff --git a/mysql-test/suite/rpl/t/rpl_do_grant.test b/mysql-test/suite/rpl/t/rpl_do_grant.test index d6a06f43d18..88120aa3512 100644 --- a/mysql-test/suite/rpl/t/rpl_do_grant.test +++ b/mysql-test/suite/rpl/t/rpl_do_grant.test @@ -316,4 +316,33 @@ DROP USER 'user49119'@'localhost'; -- sync_slave_with_master +# +# Bug #51987 revoke privileges logs wrong error code +# + +-- connection master +-- source include/master-slave-reset.inc +-- connection master + +grant all on *.* to foo@"1.2.3.4"; +-- error ER_REVOKE_GRANTS +revoke all privileges, grant option from "foo"; + +## assertion: revoke is logged +-- source include/show_binlog_events.inc + +-- sync_slave_with_master + +## assertion: slave replicates revoke and does not fail because master +## logged revoke with correct expected error code +-- let $err= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1) + if ($err) +{ + -- die UNEXPECTED ERROR AT SLAVE: $err +} + +-- connection master +DROP USER foo@"1.2.3.4"; +-- sync_slave_with_master + --echo "End of test" diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index a8828d15cae..dd256c70ecb 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -6117,19 +6117,19 @@ bool mysql_revoke_all(THD *thd, List &list) VOID(pthread_mutex_unlock(&acl_cache->lock)); - int binlog_error= + if (result) + my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0)); + + result= result | write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); - /* error for writing binary log has already been reported */ - if (result && !binlog_error) - my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0)); /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; - DBUG_RETURN(result || binlog_error); + DBUG_RETURN(result); }