From: Jon Olav Hauglid Date: January 10 2011 3:47pm Subject: bzr commit into mysql-trunk branch (jon.hauglid:3479) Bug#53322 List-Archive: http://lists.mysql.com/commits/128326 X-Bug: 53322 Message-Id: <201101101548.p0ACWAPY022484@rcsinet13.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1856148119675676263==" --===============1856148119675676263== 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 15:47:56 +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 15:47:56 +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 15:47:56 +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 */ --===============1856148119675676263== 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: 1d1d3d79571a2b0ab33fd9d991c17c3be968863c # timestamp: 2011-01-10 16:48:00 +0100 # base_revision_id: matthias.leich@stripped\ # yeax7y275a9ej35o # # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWctZ8l4ABSlfgFQQfXf//3// /uq////wYAyvuy83Ht0cAAOO0lAudOdLDVVRJjVrUgZCSQiZMRono0ZBqek0aKeZTUyekeoPJB6j TQeoASpok2hT8ESMjTQAAAAAAAAAEFMSeiNGgDQAAAAAAAAAASIghU/VPJE/EpnqTTaJnqaNT0Rm ozUxB6jEwI2gcZGmTE0GTJhNMgZDQGgNMmhgBNAYSRAgBNBoIEw1NT1PUxqI0GmQ0ep6gGj0n6pA RqWlj4/Lzep2KjvavXufgdjwMzMOPl8f+9cRfPfasJf2wPPn3T8S4c5tzrtH037pmpkVhMn/ptKm AmlTfjE9UyxhIQeoB7SVXbKLRTAqQLBHZvcipsCuSQtK8TiLohBuyYMwOFgk/TmH82gzNLJo2bnx behpZI8DNUSTUa6PX10iPewIkQLwV7Ji0OpAW6UPPkG6iFUNb4E/FXDQkIEQCB2OwiuhJAoRHCSZ o6kVDYDy2UnSQmBCZBNSKk9BTGLX33i7G8nllWbunW39RoNurg7ZzHxNw1hcqgOTaZhSxFyT4Lpn 9C4G2mJgxnR+gc8X8AGtXN0pdz0zZQy5TyF+YoB+EgDBn6yZGFP5LCSgeNgUn517IWm1quEfohDZ 5WBAPSb8LsxEWslXH2Y/otp5L8iwFVJ6rYvQI9ch2rv+xXjaBb4ZFofEl8AqlmxVTJ3d5iOYy345 ULfarIS02fAlWccq1hdb4jQyjiSEGg2uNLhMWNhQKdQWXISSyuD1sJkEVbqBLsUkkleEv3By48Yp ve5xN38neylc+GatZeTM0haMWZBg4I3s4eIqFVAQEDQR4mxtDBg0MaabYsGWpMRDBtbuJFYTEN/+ 7WkOncYsCto2xQJPtKDJDqW5rKq+RTEGQx/ztdFvd1bR8lTooiE+Zl4kRki8C85jFIE8xQ84EezD FiwPtElmIB3AFe6xTMwzXfBIKXtqMz7hFDtiUS7WCPE+kvcNPJPfhT7Rsd+rdI5H7DUjXcripJYo dIuGLVmMvpKJd3G8KUsCuCdZ4dDUAwYTsEGTdeXoGYShCZMcOJUOSGiMJMCXJ4h2RJDkbikQiSUx xoGBUXlEV1K38pnIp/17KXdgj1sq1jiYZgabMyKMZmsjKOruoEkJv3OhOe/YdI3pXXNITBOU5RoE 6yt89fTpvrL7JIcKl776jgERF5oG8kcSOG7Nd04395bHIpoGpZ1ma1kdJRFqPMRWWmu4hsTg+KTM hPj4MHIOk1GkCrlr4jZyLDZcdaiZQ3wcWP521GBnqO4j7SWZtw2WQWl408QgYjkagsI6yUyEMlPh M1GjEY4apb+ozryMrIlucjMiSyRKZ4jboqasGeskOncsesRZuh19m0pXUM3JHqfgPyL/XLfhlqnK JvvHIl8AgU+5b4Yx6JiOB2RtKRy6jERGs5EqnI2QTvUsCNJG6O4uIkLLVzmUOw0I9JuVa3GhCqIi xoXYBAdagbIyxhIaRbI7/OVXE0rvMdsUPHJj7DTtMjsJ31axsx8bdZMe8+3G4qJK1qxFibIsJlN5 QK7ULIEiBONqKR48yDEVnEanpQiVMlAJtGCy8TwwSMrzB15DPowmXMeakeOqbWtk6CDCaAwXdkyT 6i2ppSSa+2RkTtYpUH38oCLYLoWwRcFldiWiMQYFoWh3dQwFfB8a7Z5uU7xlpsuFhfvvAwLBctVQ 7DwU739wdUxlYw2wex1WpLilBW/Wvb9SDl5KiR4HIheID9Rc4Le+lEKPgC0hqTbfvQuYLclz/kIY FhtqgugIUCB3Aj1j5xAxGy6I5hZJH9WPzGRR0IxiLsFM+Q8AUkGsE4JyzMPVi4IAwJOCbIWwcLww AtA9RxRtBZkmYmITRUCuvnQigfnsEwXsBYgr6AYDgfED1Lg4nEWYwKigIVyYWYhRkJw/ySE5mhDk RC1idAXmo1FpagN4KhEitzBNC1JxUMRbUYhigzNyAtnvFWjEUQTl4YVgQFvNjiMhZ1kyKFJC1oT1 t8xtZWIThaJrkE0OHxGXzR0jNhyDYIVA0NiDgA5WkYAwVlwLgvZ58bgX1EwVpiKSgQD8eDiGw/18 vDFE/KccKUH+QTImQoRfikm1yxRBAxCgvgQzaZ+Q0wHn4MTeJj+k+yTV7LSCmkJoEx+8pSInqcHk VL6/EAjykhmcAz4Cu+cNSGPevMzj+6SpOVrOWK1UwxJKnAECuxQSDAU6E98qRTaVYNDQewvdGkVg rZsFcyo7bPLaeXp95UbB2c8/Q9mU3FzGjUsZG5ldhBSsEA0EvofCCO07SUOxAMjXqcG6B1iPoInX 8hjI4G8zNeR8k57Qoq5iInhbzCvUXoCdbJEmBOATCdqA0cDNgq3hZsaI6TVGcJCMWgTHlrMDvld2 mEXFMQO5MS2GiW1OEOs9hhj4WxmjgTQ/9JCDjDkYl41+/kEjclcMC0G2tVMA1iPII3I69VUA5tWl 0naa8tOEjQpJwmE9oV2S4gIdEH2MQMWG4388O466ezuLDUaodeIuXUt5PK4Z25lGpBVizp5Cs4aD RoSoee0G4LfnLkBiimSS5CxwdsnZ+WOmLRMa+fFqaFlD5AUhEYc6vLlrhb0tj9XEwS2nQ7e8icWV jvEGjtS2WJyNQidytnT7339VFIcPx00CpjwHdkJmL6cuU8YxP3xIKFkQBwh196cFAfGpK46Sq9He 2n3sHUJki42Dy9c5q7PmHkYK093KYRIh1COOzrP8XA0rSpWcxjxG3mCisji67zKZrPcQ9EVhRcjv qSdk4/mI5nwAgu8560qTQR4AWEsz5Dq7cGviVrrZrzaVDw9oHXjCnBI/sIdLmIZLyZdMy+CUV8Dh vJoDEAv0XaRsPYdCSctfdcXcVNEn637N6Tkh0CWxXMcEROJJGoExJZdAOHWln+cCB2YNUQu2sGgW FoUlM1PLsuyYhJY2TMMDLKpArV9KtFUbA4jBYNSXrUPJAmtoxqb2yKuMR8TtBlmzx1XoGZZWMJnH IMOUv2nOLZGuJuedos28sTDFeNBlCQjFCyIa6qI7lyb9/1Lo1UTiYZ0k6cZMZJp5uHaXBqPAarmC yzI/jVhMypwZDnQPAgXgwYEmZMKgIY5jM/mDVzz31WAEDOOeQAuB1SxufneIqZDqxHQXXCKJ+6eY JaIUlp0EeIXDGTd4yUzInTJIzZ03NJlt1UNi2DEoTEilCB4rkoFkHSMJCVaQd4CiUokJa2pJTGPZ LCRaucmCYXSS3W6mipVmFXDFdDUNDXEazAoI3b96Ab2b0XLh1GLbuiBABdT81KKVBSEFq1Jj1YIA XXvBINeBIashSoAhFO0daUcoDTAZKWauFgVA09Z/CKmcmmHqktorYjsg8HWOu4bptslM4SHAoC4u DXGgcZd7JkNAKFtYxe4lBEVOfca7IfCXmXSxL1s8jP6TTabADTLEz3XOwzYRC1OWU4KqJPxaEdGw QGo2DywyDEaKquS1phwNvNwqI6zxjlyMEGmXukqqVwyBwtVBhHenlhkTjcrLH0rXQ7zhQpWg0RCm Nsdz7fy0ZlTHLJ6BaInWarbIJZirGIoXDvI6+k2GeQca/Btt0JYB3HMFaNkm3MLUsDIUBHeP34Hi kSO3JR7W5DDGAVVRle6gXUh3VEgr6CAXV1BMiVUPQUiEcrSg/r0r4kClwAyrt1DFrci+FA1S5N3B iXCaFFzjivm59bCOczbao/qsj0a0cioySFNk4OP1FNxY7J0ql1E4kJ1Z6WXTRKC2lXSdvid1odSD twGYq9PM/BV3gtqvcDaJgZDgs7iwG94pT2lQaXGeElhr2aiLoMRMaVMRQtUBRGjveLcajmjU43A9 BsqPLNmHh2lKg834TwyXVKs3VJGxE8TDxvnWgc8qUyJjM4gnPu+ssmWh7cICLC5//i7kinChIZaz 5Lw= --===============1856148119675676263==--