From: Jon Olav Hauglid Date: December 20 2010 12:59pm Subject: bzr commit into mysql-trunk-bugfixing branch (jon.hauglid:3450) Bug#53322 List-Archive: http://lists.mysql.com/commits/127297 X-Bug: 53322 Message-Id: <201012201259.oBKCxPe1013195@rcsinet13.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============6146229278288719739==" --===============6146229278288719739== 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-bugfixing-bug53322/ based on revid:bar@stripped 3450 Jon Olav Hauglid 2010-12-20 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 FUNCTION (UDF) implementation to open mysql.func before locking THR_LOCK_udf. The DROP FUNCTION (UDF) implementation is changed so that THR_LOCK_udf is unlocked before opening mysql.func. 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 2010-12-20 12:59:07 +0000 @@ -468,3 +468,33 @@ 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"); +ERROR 42000: FUNCTION test.metaphon does not exist +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 2010-12-20 12:59:07 +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,71 @@ 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 +--error ER_SP_DOES_NOT_EXIST +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 2010-12-20 12:59:07 +0000 @@ -459,6 +459,9 @@ int mysql_create_function(THD *thd,udf_f if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) thd->clear_current_stmt_binlog_format_row(); + tables.init_one_table("mysql", 5, "func", 4, "func", TL_WRITE); + table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT); + mysql_rwlock_wrlock(&THR_LOCK_udf); if ((my_hash_search(&udf_hash,(uchar*) udf->name.str, udf->name.length))) { @@ -501,9 +504,8 @@ 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))) + if (table == NULL) goto err; table->use_all_columns(); restore_record(table, s->default_values); // Default values for fields @@ -557,6 +559,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) @@ -580,7 +583,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 +595,12 @@ 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; + goto exit; 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 +608,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 */ --===============6146229278288719739== 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-bugfixing-bug53322/ # testament_sha1: 5555bd21a7e544be07e72d90e51d0bdcad93462c # timestamp: 2010-12-20 13:59:10 +0100 # source_branch: file:///export/home/x/mysql-5.5-bugteam/ # base_revision_id: bar@stripped # # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWUaKG/0ABRLfgFQQfXf//3// /uq////wYAyMvt5296e91eD2msiz00g3ve3m9lOlABnbQa16DYSSTRMNSaTwpvQyCnkQejQhp6ZQ PU9TQyaD1ACURNMTTTQITTU0MmEDJoDQABoAA0EiibRNEIU96mjUwp6mj0anlPU2kNAyDQ0BoGmg kREmkeoxRpnqjE00fqjyhoA0MgD1ABkNNDjI0yYmgyZMJpkDIaA0Bpk0MAJoDCSIgAJiDQExNBGm k9KNMmgyAyAHqPUegqwMd3ftiUGLp0tjWaRuC7YFEd9R/vrvxZZpsjZZnnLyeGPGZHHO6d89OLho cbRiFj114rMCErW49lKds7zTDDU+DrjKv5z5csEXObzej9ZfDrVnY0jPBLwMWTTCgOFJY7bhFclL tc777ubwuhHFFHpkpdJ3XSa1HDfvpQa2EEySPsXRkxtPFAbtqIXHNWaYG+WJX6rotgMmZmSMNXrQ bdIxebg3Tn2YWw5omN9XBz+m5ZzwlJ5xjPIes7YirG956tKzN0bt/SN43Y2e0YE8pnGrCqA2zUU0 IqSuRZDSt9pttMTBjK6OcOaLe+Bum9v50uVyZrYa7htF9BPDslAYPHToLK4YJ/QoFAHmgFox4pZq N2qUjh7O4Jh3xKfJlviKPKMcPe1/JevYv6LgkHMISqGDwq3XDFjP3JMXSkuG8kHOO7wWuxUg+93d 5RHiMu19Ew9Pkp6ZJNeXWSSk240qmuXyGvhcXjDwwo+cxmymJGImE5GOmmK3Y30Y0qUVLG2AzVes IRaD/Udjj3HS8bGEjkr43gppSNBX7a7UxUOBCeTJWCrYQQENBHC2NoYMGhjTTbNoa6aZGNU2gnOK A/xf2ppTNGFNGHG9WKLUWrPkb0Q0jREPzic/q/bCE2h5ISbDFj7pC+X6/t0TFVL+Md0/WyaHFJLo RD0AOLPhVDMM3WqsuoRuBE/C1ReJjNESJZmB9RrLThnjXb+cntw1USG8wL0NFUk1iZIYTpFIxtNB n3lkvDmFYuHWms+3nlVCJNPdTpqHAESqVJBwaGMyY0BgTGJSEPGfBylJhRNkD6VjBHLc1l6kLEKG 4ReCMv8JlMS10Sstf9+RQQZVO1bSmPtuG0aGNgzPZIHvki+hE6dVxB52jb5Og08tg4yeFTfBiVGI uXlu3SM4z2kudEw250KsgEjaCZmONA7RmnWsNV2+RkP2gwSe5ilmnMia3C1jlValfSoRWbBOELgR IhQ0SsFqghNO9pAbndtViG+W3NIxLEwc7QomR/Yl95jwmeSV7b6S26X14RyKjKhBJSBwpKwLiqdw MMrq74GnqCEsyug/HLox8XOYX0rq2T3jVgjeKnAHjOS0HHJwTGdFdahQ2ktULRV1h1SnQKOT0jo9 FttFeKG2wGaPMmps54lIvRwIGNV86rJItbgxoEQCdRmN/bMchj5FhLtJ1US7s6EZRiPALS0a8JnH KHg1EnhKe7aS5Ua60VloydZ4DRukzSSjasMFtEGGDF1Iyo5tRvD8ZSIRJkygx+KGyhZQZPIuOob5 alV9L1WlqMIowcKaxuuGLzQ+KcDTJuamZxcWD42Pa1VBJzW4bpli2ERSxxE1WmuI24RkkPv6AVW0 Opa4FSeyQv0NKS3wCQkh1dAxFWz7uE8/1HYX3obXW1XtdixAVIopOCc2o1d4c8DV2P6eKeUldQuZ Kapn8q8XcgyXNZIwOFC4QOIXMCu56IXKCybDYxjORC0le3afxCGgqNswFkCUkA6gSPYkGUlDFpJE vSLYkfez1DVpIRswFzij8jGeNAWyyWaFME+gPoylCcGEk4JrxYuFpcBWB9B0o1As55iYJaSUARp7 EIwC3l2iYL9AWQLVjsBgTA9QHt2GhuF7jBVJglrYrglhQUg/a8CgTXIRpiTAlpE4gtMDCexAZgph 4kVrYJUKxxSXi1K8L0sS9AXVk2aT0ovE4Jy0LqQICtzyxiKdgmwFZUUyIU6FOkOVN8xq6AScpE1S WM0GBg/FMvmjiM124v0glOFBklmA9KRcMFJYhZnd7tvCwFX6TgrNCWU7xifh0942H3fHniifEd6F KDTBMicEIxfGSbMRYUQUyJPW0fTh5ycDrNhs4NfrLbzYS7e3Gpy0BRdcW17NQI7SQM2IF17qxN7v hsQU5k9ZzGXvxTGictrEOXUjMUgAYcma0Qbwap05TEaiy2k5DXmokfgC23rthZXTtJcZk3eCBuUx 7ltOwrXVbLJevg40K0SPZYoCKWIhMU/yLAUUUnoUB7hAyLdjjjWnEyOxAiOQLfE/mTEc8biB+SgV eh2CQ1KmU3HW/xrMShAVxaRRoUgUBGpAckgOphbwBfa8CSTWDNBCMbQJj1Ly04DARZ2csBalMQO0 mJGw8BdE4UvumLbuBVMUonlQ8RBsf3neVFVevaETSlaO4LUNpaeVAeYQrR1vmgHi06Uu85GN2vXs lHKkxxKd4V2pcOAbolsNJMLzsRdaW3ulZzneaPThXxXkpeNbp37mUqrFkK5QI5ZGWCV9kT2Bsft6 9DDeZnJAYUXJJfFLGOUOGDRlyjb51875Gu3VxBTJ5PkK4quNm/DiUK6zM4zxEbr94d1A0jYEsZlT kUMs6lDpDj4V3K1vH/WqwV055euBzx6n2aEoeOpBMYRAHCHHonBQL4MTpVnIn2Whcz/ewd4mSPU4 3DuC05i8UkUpWGhoIwdAjkP4uMpVIMxotrnwjXzmJVpW913nwlPcVEPqRQNMuJ2nSdgcd8IOBBZm zowoyXDuCnN2248Dym+PqaV3M3M5GJDxA43QJjUkMLzZJmWcSqARXM1dCVAWAHLSI1MUdxzSTr2E bvTicTbVu6JOkPEo18GXijzIovSGI3MX7QcOCUfnAgcbWnIX19ve4bArsDA0WYfDz543pJaGTMMD LJTo9VJ1vXAWox7gZMGprzquJAnDdaXqn5a/yPeDLTqry6oGZaGoG1jCLdB05HMXGVfIyXWJ6C1e BmmGLgWATEgtmcQynmR1Xc33/BcCVMDDYAnTsmUhi50KgvOw3gCu0EJa5C2XNkObx4ECFQOFZBmT CmBDaDGGgN+1Z2c8cwCJpHgRA5Pkr3Ia4INzCfqcqqfSmgJiqNxtOsv/lrJaOqXAarRcmki5hmc0 mW2xbIwQTMDtXcoFQMDFISrJTxQqJSiQlm4klMdcqAqGGTnUGEJJX6q8mqCGWo5NKyGpNDXYaE5u 12oBuewNjFhnxL2w6wIIFyfrJFKYUggrWZM52EJIbueJkpr9JDViFKgCEUw25RxgMmAZKTArFaTg 2J+ECDSJw7gWQqIp2QdnVvLFhvDMzoNITmssDmI5HIOy4ToIGPeyZDRC45sr/kUgiKllO800w9ZP Irk0FhqvNYjLzH1GSQbL7jDXW7JmtdzJoMR5yJ4EiYQVyg6MTSNRPME4yJFQskxMBl3uE5HAt2li DTd6SKWieexEguqjSOlO9rmNTCjHvVFWs7YUbnJyKTeb9+r421khPTS1orXhkY6XcKFIUCdfC83s rjzK66g4F3W23WWCiCDKrk8qey0sa1zKKRGBGGueIMyUhcEO5tpU45YE88ZZXUCqaB0nUgUbiASj AKyqDzuCOG1U2Wwb/qmc6vtAFSJLgFJLsJteGiTb1Cq4YTRmXaJcfRz6mEeEpph9dEN+KNxMXpCl GTg4/Em1FLjJ0p1xJYkJdE9UUU5E3A6eR1pDiI6WDMT+3vP2KgvBZKxwMhMDIdIwrKUN8RSS5E4c XOcZ9pw47yTvLSozVRJuUBRNntAXUgt5jQImVY3kfiNgjYI+7VqIh6GKjA7VHtf3bDrpG0jMIyIu vZQd48FJoEWFTxG4kuiY17PGVXIIVPLgtwkTd/xdyRThQkEaKG/0 --===============6146229278288719739==--