From: Dmitry Shulga Date: June 22 2011 1:06pm Subject: bzr commit into mysql-5.1 branch (Dmitry.Shulga:3634) Bug#47870 Bug#11756013 List-Archive: http://lists.mysql.com/commits/139686 X-Bug: 47870,11756013 Message-Id: <201106221306.p5MD6nJI008190@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============8113885481926433384==" --===============8113885481926433384== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/shulga/projects/mysql/mysql-5.1-bug11756013/ based on revid:davi.arnaut@stripped 3634 Dmitry Shulga 2011-06-22 Fixed Bug#11756013 (formerly known as bug#47870): BOGUS "THE TABLE MYSQL.PROC IS MISSING,..." There was a race condition between loading a stored routine (function/procedure/trigger) specified by fully qualified name SCHEMA_NAME.PROC_NAME and dropping the stored routine database. The problem was that there is a window for race condition when one server thread try to load a stored routine being executed and the other thread tries to drop the stored routine schema. This condition race window exists in implementation of function mysql_change_db() called by db_load_routine() during loading of stored routine to cache. Function mysql_change_db() calls check_db_dir_existence() that might failed because specified database was dropped during concurrent execution of DROP SCHEMA statememt. db_load_routine() calls mysql_change_db() with flag 'force_switch' set to 'true' value so when referenced db is not found then my_error() is not called and function mysql_change_db() returns ok. This shadows information about schema opening error in db_load_routine(). Then db_load_routine() makes attempt to parse stored routine that is failed. This makes to return error to sp_cache_routines_and_add_tables_aux() but since during error generation a call to my_error wasn't made and hence THD::main_da wasn't set we set the generic "mysql.proc table corrupt" error when running sp_cache_routines_and_add_tables_aux(). The fix is to install an error handler inside db_load_routine() for the mysql_op_change_db() call, and check later if the ER_BAD_DB_ERROR was caught. @ sql/sql_db.cc Added synchronization point "before_db_dir_check" to emulate a race condition during processing of CALL/DROP SCHEMA. modified: mysql-test/r/sp_sync.result mysql-test/t/sp_sync.test sql/sp.cc sql/sql_db.cc === modified file 'mysql-test/r/sp_sync.result' --- a/mysql-test/r/sp_sync.result 2010-01-12 14:16:26 +0000 +++ b/mysql-test/r/sp_sync.result 2011-06-22 13:06:27 +0000 @@ -20,4 +20,16 @@ SET DEBUG_SYNC = 'now SIGNAL go'; # code, this test statement will hang. DROP TABLE t1, t2; DROP PROCEDURE p1; +# +# test for bug#11756013 +# +DROP SCHEMA IF EXISTS s1; +CREATE SCHEMA s1; +CREATE PROCEDURE s1.p1() BEGIN END; +SET DEBUG_SYNC='before_db_dir_check SIGNAL check_db WAIT_FOR dropped_schema'; +CALL s1.p1; +SET DEBUG_SYNC='now WAIT_FOR check_db'; +DROP SCHEMA s1; +SET DEBUG_SYNC='now SIGNAL dropped_schema'; +ERROR 42000: Unknown database 's1' SET DEBUG_SYNC = 'RESET'; === modified file 'mysql-test/t/sp_sync.test' --- a/mysql-test/t/sp_sync.test 2010-01-15 08:51:39 +0000 +++ b/mysql-test/t/sp_sync.test 2011-06-22 13:06:27 +0000 @@ -1,6 +1,9 @@ # This test should work in embedded server after mysqltest is fixed -- source include/not_embedded.inc +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + --echo Tests of syncronization of stored procedure execution. --source include/have_debug_sync.inc @@ -54,5 +57,31 @@ connection default; DROP TABLE t1, t2; DROP PROCEDURE p1; +--echo # +--echo # test for bug#11756013 +--echo # +--disable_warnings +DROP SCHEMA IF EXISTS s1; +--enable_warnings +CREATE SCHEMA s1; +CREATE PROCEDURE s1.p1() BEGIN END; + +connect (con3, localhost, root); +SET DEBUG_SYNC='before_db_dir_check SIGNAL check_db WAIT_FOR dropped_schema'; +--send CALL s1.p1 + +connection default; +SET DEBUG_SYNC='now WAIT_FOR check_db'; +DROP SCHEMA s1; +SET DEBUG_SYNC='now SIGNAL dropped_schema'; + +connection con3; +--error ER_BAD_DB_ERROR +--reap +connection default; +disconnect con3; + SET DEBUG_SYNC = 'RESET'; +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc === modified file 'sql/sp.cc' --- a/sql/sp.cc 2010-06-11 12:52:06 +0000 +++ b/sql/sp.cc 2011-06-22 13:06:27 +0000 @@ -708,6 +708,37 @@ Silence_deprecated_warning::handle_error } +struct Bad_db_error_handler : public Internal_error_handler +{ +public: + Bad_db_error_handler() + :m_error_caught(false) + {} + + virtual bool handle_error(uint sql_errno, const char *message, + MYSQL_ERROR::enum_warning_level level, + THD *thd); + + bool error_caught() const { return m_error_caught; } + +private: + bool m_error_caught; +}; + +bool +Bad_db_error_handler::handle_error(uint sql_errno, const char *message, + MYSQL_ERROR::enum_warning_level level, + THD *thd) +{ + if (sql_errno == ER_BAD_DB_ERROR) + { + m_error_caught= true; + return true; + } + return false; +} + + static int db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, ulong sql_mode, const char *params, const char *returns, @@ -725,7 +756,7 @@ db_load_routine(THD *thd, int type, sp_n ha_rows old_select_limit= thd->variables.select_limit; sp_rcontext *old_spcont= thd->spcont; Silence_deprecated_warning warning_handler; - + Bad_db_error_handler db_not_exists_handler; char definer_user_name_holder[USERNAME_LENGTH + 1]; LEX_STRING definer_user_name= { definer_user_name_holder, USERNAME_LENGTH }; @@ -766,6 +797,7 @@ db_load_routine(THD *thd, int type, sp_n goto end; } + thd->push_internal_handler(&db_not_exists_handler); /* Change the current database (if needed). @@ -776,9 +808,17 @@ db_load_routine(THD *thd, int type, sp_n &cur_db_changed)) { ret= SP_INTERNAL_ERROR; + thd->pop_internal_handler(); goto end; } + thd->pop_internal_handler(); + if (db_not_exists_handler.error_caught()) + { + ret= SP_INTERNAL_ERROR; + my_error(ER_BAD_DB_ERROR, MYF(0), name->m_db.str); + goto end; + } thd->spcont= NULL; { === modified file 'sql/sql_db.cc' --- a/sql/sql_db.cc 2010-12-10 07:48:50 +0000 +++ b/sql/sql_db.cc 2011-06-22 13:06:27 +0000 @@ -26,6 +26,7 @@ #ifdef __WIN__ #include #endif +#include "debug_sync.h" #define MAX_DROP_TABLE_Q_LEN 1024 @@ -1702,6 +1703,8 @@ bool mysql_change_db(THD *thd, const LEX } #endif + DEBUG_SYNC(thd, "before_db_dir_check"); + if (check_db_dir_existence(new_db_file_name.str)) { if (force_switch) --===============8113885481926433384== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/dmitry.shulga@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: dmitry.shulga@stripped\ # g07rqzejnv1scy93 # target_branch: file:///Users/shulga/projects/mysql/mysql-5.1-\ # bug11756013/ # testament_sha1: 1b7dfae596800509903d237eeea032f42bff7af0 # timestamp: 2011-06-22 20:06:43 +0700 # base_revision_id: davi.arnaut@stripped\ # gek17uxbyt23m0ct # # Begin bundle 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 mDGCa8r16Cq5VL6FSUjDf6FH/i7kinChIU20DXg= --===============8113885481926433384==--