From: Jon Olav Hauglid Date: January 10 2011 4:27pm Subject: bzr commit into mysql-trunk branch (jon.hauglid:3479) Bug#53322 List-Archive: http://lists.mysql.com/commits/128335 X-Bug: 53322 Message-Id: <201101101627.p0ADTtxT018944@acsinet15.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============2421844844575132441==" --===============2421844844575132441== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///export/home/x/mysql-trunk-bug53322/ based on revid:matthias.leich@stripped 3479 Jon Olav Hauglid 2011-01-10 Bug #53322 deadlock with FLUSH TABLES WITH READ LOCK and DROP FUNCTION This deadlock could occur between two connections if one connection first locked the mysql.func table (using either FLUSH TABLES WITH READ LOCK or LOCK TABLE mysql.func WRITE). If the second connection then tried to either CREATE or DROP an UDF function, a deadlock would occur when the first connection tried to use an UDF function. The reason for the deadlock was the way the THR_LOCK_udf rwlock was used in the UDF handling code. For CREATE or DROP FUNCTION (UDF), THR_LOCK_udf was write locked before mysql.func was locked and opened. This meant that another connection first locking mysql.func and later using an UDF function (and thus locking THR_LOCK_udf), could cause a deadlock. This patch fixes the problem by changing the CREATE and DROP FUNCTION (UDF) implementation to open mysql.func before locking THR_LOCK_udf. Test case added to udf.test. modified: mysql-test/r/udf.result mysql-test/t/udf.test sql/sql_udf.cc === modified file 'mysql-test/r/udf.result' --- a/mysql-test/r/udf.result 2010-03-24 15:03:44 +0000 +++ b/mysql-test/r/udf.result 2011-01-10 16:27:45 +0000 @@ -468,3 +468,34 @@ DROP FUNCTION myfunc_double; DROP TABLE t1; # End of 5.1 tests. +# +# Bug#53322 deadlock with FLUSH TABLES WITH READ LOCK and DROP FUNCTION +# +CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +# Connection con1 +FLUSH TABLES WITH READ LOCK; +# Connection default +# Sending: +DROP FUNCTION metaphon; +# Connection con1 +# Wait until DROP FUNCTION is blocked by GRL +SELECT metaphon("foo"); +metaphon("foo") +F +UNLOCK TABLES; +# Connection default +# Reaping: DROP FUNCTION metaphon +# Connection con1 +FLUSH TABLES WITH READ LOCK; +# Connection default +# Sending: +CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +# Connection con1 +# Wait until CREATE FUNCTION is blocked by GRL +SELECT reverse_lookup("127.0.0.1"); +UNLOCK TABLES; +# Connection default +# Reaping: CREATE FUNCTION metaphon ... +DROP FUNCTION metaphon; +DROP FUNCTION reverse_lookup; === modified file 'mysql-test/t/udf.test' --- a/mysql-test/t/udf.test 2010-03-24 15:03:44 +0000 +++ b/mysql-test/t/udf.test 2011-01-10 16:27:45 +0000 @@ -1,4 +1,5 @@ --source include/have_udf.inc +--source include/not_embedded.inc # # To run this tests the "sql/udf_example.c" need to be compiled into # udf_example.so and LD_LIBRARY_PATH should be setup to point out where @@ -535,3 +536,70 @@ DROP TABLE t1; --echo # --echo End of 5.1 tests. + +--echo # +--echo # Bug#53322 deadlock with FLUSH TABLES WITH READ LOCK and DROP FUNCTION +--echo # + +--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB +eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB"; +--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB +eval CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "$UDF_EXAMPLE_LIB"; + +--echo # Connection con1 +connect(con1, localhost, root); +FLUSH TABLES WITH READ LOCK; + +--echo # Connection default +connection default; +--echo # Sending: +--send DROP FUNCTION metaphon + +--echo # Connection con1 +connection con1; +--echo # Wait until DROP FUNCTION is blocked by GRL +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for global read lock" AND + info = "DROP FUNCTION metaphon"; +--source include/wait_condition.inc +SELECT metaphon("foo"); +UNLOCK TABLES; + +--echo # Connection default +connection default; +--echo # Reaping: DROP FUNCTION metaphon +--reap + +--echo # Connection con1 +connection con1; +FLUSH TABLES WITH READ LOCK; + +--echo # Connection default +connection default; +--echo # Sending: +--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB +--send +eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB"; + +--echo # Connection con1 +connection con1; +--echo # Wait until CREATE FUNCTION is blocked by GRL +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for global read lock"; +--source include/wait_condition.inc +# Can return different results depending on platform +--disable_result_log +SELECT reverse_lookup("127.0.0.1"); +--enable_result_log +UNLOCK TABLES; +disconnect con1; +--source include/wait_until_disconnected.inc + +--echo # Connection default +connection default; +--echo # Reaping: CREATE FUNCTION metaphon ... +--reap +DROP FUNCTION metaphon; +DROP FUNCTION reverse_lookup; === modified file 'sql/sql_udf.cc' --- a/sql/sql_udf.cc 2010-12-02 05:40:58 +0000 +++ b/sql/sql_udf.cc 2011-01-10 16:27:45 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -452,6 +452,10 @@ int mysql_create_function(THD *thd,udf_f DBUG_RETURN(1); } + tables.init_one_table("mysql", 5, "func", 4, "func", TL_WRITE); + if (!(table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT))) + DBUG_RETURN(1); + /* Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for CREATE FUNCTION command. @@ -501,10 +505,6 @@ int mysql_create_function(THD *thd,udf_f /* create entry in mysql.func table */ - tables.init_one_table("mysql", 5, "func", 4, "func", TL_WRITE); - /* Allow creation of functions even if we can't open func table */ - if (!(table = open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT))) - goto err; table->use_all_columns(); restore_record(table, s->default_values); // Default values for fields table->field[0]->store(u_d->name.str, u_d->name.length, system_charset_info); @@ -557,6 +557,7 @@ int mysql_drop_function(THD *thd,const L char *exact_name_str; uint exact_name_len; bool save_binlog_row_based; + int error= 1; DBUG_ENTER("mysql_drop_function"); if (!initialized) @@ -568,6 +569,10 @@ int mysql_drop_function(THD *thd,const L DBUG_RETURN(1); } + tables.init_one_table("mysql", 5, "func", 4, "func", TL_WRITE); + if (!(table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT))) + DBUG_RETURN(1); + /* Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for DROP FUNCTION command. @@ -580,7 +585,8 @@ int mysql_drop_function(THD *thd,const L (uint) udf_name->length))) { my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), udf_name->str); - goto err; + mysql_rwlock_unlock(&THR_LOCK_udf); + goto exit; } exact_name_str= udf->name.str; exact_name_len= udf->name.length; @@ -591,11 +597,8 @@ int mysql_drop_function(THD *thd,const L */ if (udf->dlhandle && !find_udf_dl(udf->dl)) dlclose(udf->dlhandle); + mysql_rwlock_unlock(&THR_LOCK_udf); - tables.init_one_table("mysql", 5, "func", 4, "func", TL_WRITE); - - if (!(table = open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT))) - goto err; table->use_all_columns(); table->field[0]->store(exact_name_str, exact_name_len, &my_charset_bin); if (!table->file->ha_index_read_idx_map(table->record[0], 0, @@ -603,36 +606,23 @@ int mysql_drop_function(THD *thd,const L HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { - int error; - if ((error = table->file->ha_delete_row(table->record[0]))) - table->file->print_error(error, MYF(0)); + int delete_err; + if ((delete_err = table->file->ha_delete_row(table->record[0]))) + table->file->print_error(delete_err, MYF(0)); } - mysql_rwlock_unlock(&THR_LOCK_udf); /* Binlog the drop function. Keep the table open and locked while binlogging, to avoid binlog inconsistency. */ - if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) - { - /* Restore the state of binlog format */ - DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); - if (save_binlog_row_based) - thd->set_current_stmt_binlog_format_row(); - DBUG_RETURN(1); - } + if (!write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + error= 0; +exit: /* Restore the state of binlog format */ DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); - DBUG_RETURN(0); -err: - mysql_rwlock_unlock(&THR_LOCK_udf); - /* Restore the state of binlog format */ - DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); - if (save_binlog_row_based) - thd->set_current_stmt_binlog_format_row(); - DBUG_RETURN(1); + DBUG_RETURN(error); } #endif /* HAVE_DLOPEN */ --===============2421844844575132441== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/jon.hauglid@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: jon.hauglid@stripped # target_branch: file:///export/home/x/mysql-trunk-bug53322/ # testament_sha1: 9730359ab5481745f0fe93a2ad7a0bd7e80302e5 # timestamp: 2011-01-10 17:27:48 +0100 # base_revision_id: matthias.leich@stripped\ # yeax7y275a9ej35o # # Begin bundle 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 4U1I --===============2421844844575132441==--