List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:October 14 2010 10:12am
Subject:bzr push into mysql-trunk-merge branch (alexander.nozdrin:3269 to 3270)
View as plain text  
 3270 Alexander Nozdrin	2010-10-14 [merge]
      Auto-merge from mysql-5.5-bugteam.

    modified:
      mysql-test/extra/rpl_tests/rpl_start_stop_slave.test
      mysql-test/include/mtr_warnings.sql
      mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result
      sql/item_func.cc
 3269 Alexander Nozdrin	2010-10-13 [merge]
      Auto-merge from mysql-5.5-bugteam.

=== modified file 'mysql-test/extra/rpl_tests/rpl_start_stop_slave.test'
--- a/mysql-test/extra/rpl_tests/rpl_start_stop_slave.test	2010-04-28 12:47:49 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_start_stop_slave.test	2010-10-14 01:54:07 +0000
@@ -122,4 +122,60 @@ drop table t1i, t2m;
 
 sync_slave_with_master;
 
+--echo #
+--echo # Bug#56096 STOP SLAVE hangs if executed in parallel with user sleep
+--echo #
+
+--connection master
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT );
+
+sync_slave_with_master;
+
+--connection slave1
+--echo # Slave1: lock table for synchronization
+LOCK TABLES t1 WRITE;
+
+--connection master
+--echo # Master: insert into the table
+INSERT INTO t1 SELECT SLEEP(4);
+
+--connection slave
+--echo # Slave: wait for the insert
+let $wait_condition=
+  SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+  WHERE STATE = "Waiting for table metadata lock"
+  AND INFO = "INSERT INTO t1 SELECT SLEEP(4)";
+--source include/wait_condition.inc
+
+--echo # Slave: send slave stop
+--send STOP SLAVE
+
+--connection slave1
+--echo # Slave1: wait for stop slave
+let $wait_condition=
+  SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+  WHERE INFO = "STOP SLAVE";
+--source include/wait_condition.inc
+
+--echo # Slave1: unlock the table
+UNLOCK TABLES;
+
+--connection slave
+--echo # Slave: wait for the slave to stop
+--reap
+--source include/wait_for_slave_to_stop.inc
+
+--echo # Start slave again
+--source include/start_slave.inc
+
+--echo # Clean up
+--connection master
+DROP TABLE t1;
+sync_slave_with_master;
+
 # End of tests

=== modified file 'mysql-test/include/mtr_warnings.sql'
--- a/mysql-test/include/mtr_warnings.sql	2010-08-04 12:38:29 +0000
+++ b/mysql-test/include/mtr_warnings.sql	2010-10-14 10:12:00 +0000
@@ -16,6 +16,12 @@ CREATE TABLE test_suppressions (
 -- no invalid patterns can be inserted
 -- into test_suppressions
 --
+SET @character_set_client_saved = @@character_set_client||
+SET @character_set_results_saved = @@character_set_results||
+SET @collation_connection_saved = @@collation_connection||
+SET @@character_set_client = latin1||
+SET @@character_set_results = latin1||
+SET @@collation_connection = latin1_swedish_ci||
 /*!50002
 CREATE DEFINER=root@localhost TRIGGER ts_insert
 BEFORE INSERT ON test_suppressions
@@ -24,6 +30,9 @@ FOR EACH ROW BEGIN
   SELECT "" REGEXP NEW.pattern INTO dummy;
 END
 */||
+SET @@character_set_client = @character_set_client_saved||
+SET @@character_set_results = @character_set_results_saved||
+SET @@collation_connection = @collation_connection_saved||
 
 
 --
@@ -38,6 +47,12 @@ CREATE TABLE global_suppressions (
 -- no invalid patterns can be inserted
 -- into global_suppressions
 --
+SET @character_set_client_saved = @@character_set_client||
+SET @character_set_results_saved = @@character_set_results||
+SET @collation_connection_saved = @@collation_connection||
+SET @@character_set_client = latin1||
+SET @@character_set_results = latin1||
+SET @@collation_connection = latin1_swedish_ci||
 /*!50002
 CREATE DEFINER=root@localhost TRIGGER gs_insert
 BEFORE INSERT ON global_suppressions
@@ -46,6 +61,9 @@ FOR EACH ROW BEGIN
   SELECT "" REGEXP NEW.pattern INTO dummy;
 END
 */||
+SET @@character_set_client = @character_set_client_saved||
+SET @@character_set_results = @character_set_results_saved||
+SET @@collation_connection = @collation_connection_saved||
 
 
 

=== modified file 'mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result'
--- a/mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result	2010-04-29 11:20:36 +0000
+++ b/mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result	2010-10-14 10:12:00 +0000
@@ -43,3 +43,25 @@ one
 1
 include/start_slave.inc
 drop table t1i, t2m;
+#
+# Bug#56096 STOP SLAVE hangs if executed in parallel with user sleep
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a INT );
+# Slave1: lock table for synchronization
+LOCK TABLES t1 WRITE;
+# Master: insert into the table
+INSERT INTO t1 SELECT SLEEP(4);
+Warnings:
+Note	1592	Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
+# Slave: wait for the insert
+# Slave: send slave stop
+STOP SLAVE;
+# Slave1: wait for stop slave
+# Slave1: unlock the table
+UNLOCK TABLES;
+# Slave: wait for the slave to stop
+# Start slave again
+include/start_slave.inc
+# Clean up
+DROP TABLE t1;

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2010-10-05 14:35:03 +0000
+++ b/sql/item_func.cc	2010-10-14 10:12:00 +0000
@@ -3691,48 +3691,92 @@ longlong Item_master_pos_wait::val_int()
 }
 
 
+/**
+  Enables a session to wait on a condition until a timeout or a network
+  disconnect occurs.
+
+  @remark The connection is polled every m_interrupt_interval nanoseconds.
+*/
+
+class Interruptible_wait
+{
+  THD *m_thd;
+  struct timespec m_abs_timeout;
+  static const ulonglong m_interrupt_interval;
+
+  public:
+    Interruptible_wait(THD *thd)
+    : m_thd(thd) {}
+
+    ~Interruptible_wait() {}
+
+  public:
+    /**
+      Set the absolute timeout.
+
+      @param timeout The amount of time in nanoseconds to wait
+    */
+    void set_timeout(ulonglong timeout)
+    {
+      /*
+        Calculate the absolute system time at the start so it can
+        be controlled in slices. It relies on the fact that once
+        the absolute time passes, the timed wait call will fail
+        automatically with a timeout error.
+      */
+      set_timespec_nsec(m_abs_timeout, timeout);
+    }
+
+    /** The timed wait. */
+    int wait(mysql_cond_t *, mysql_mutex_t *);
+};
+
+
+/** Time to wait before polling the connection status. */
+const ulonglong Interruptible_wait::m_interrupt_interval= 5 * ULL(1000000000);
+
 
 /**
-  Wait for a given condition to be signaled within the specified timeout.
+  Wait for a given condition to be signaled.
+
+  @param cond   The condition variable to wait on.
+  @param mutex  The associated mutex.
 
-  @param cond the condition variable to wait on
-  @param lock the associated mutex
-  @param abstime the amount of time in seconds to wait
+  @remark The absolute timeout is preserved across calls.
 
   @retval return value from mysql_cond_timedwait
 */
 
-#define INTERRUPT_INTERVAL (5 * ULL(1000000000))
-
-static int interruptible_wait(THD *thd, mysql_cond_t *cond,
-                              mysql_mutex_t *lock, double time)
+int Interruptible_wait::wait(mysql_cond_t *cond, mysql_mutex_t *mutex)
 {
   int error;
-  struct timespec abstime;
-  ulonglong slice, timeout= (ulonglong) (time * 1000000000.0);
+  struct timespec timeout;
 
-  do
+  while (1)
   {
     /* Wait for a fixed interval. */
-    if (timeout > INTERRUPT_INTERVAL)
-      slice= INTERRUPT_INTERVAL;
-    else
-      slice= timeout;
+    set_timespec_nsec(timeout, m_interrupt_interval);
+
+    /* But only if not past the absolute timeout. */
+    if (cmp_timespec(timeout, m_abs_timeout) > 0)
+      timeout= m_abs_timeout;
 
-    timeout-= slice;
-    set_timespec_nsec(abstime, slice);
-    error= mysql_cond_timedwait(cond, lock, &abstime);
+    error= mysql_cond_timedwait(cond, mutex, &timeout);
     if (error == ETIMEDOUT || error == ETIME)
     {
       /* Return error if timed out or connection is broken. */
-      if (!timeout || !thd->is_connected())
+      if (!cmp_timespec(timeout, m_abs_timeout) || !m_thd->is_connected())
         break;
     }
-  } while (error && timeout);
+    /* Otherwise, propagate status to the caller. */
+    else
+      break;
+  }
 
   return error;
 }
 
+
 /**
   Get a user level lock.  If the thread has an old lock this is first released.
 
@@ -3748,10 +3792,11 @@ longlong Item_func_get_lock::val_int()
 {
   DBUG_ASSERT(fixed == 1);
   String *res=args[0]->val_str(&value);
-  double timeout= args[1]->val_real();
+  ulonglong timeout= args[1]->val_int();
   THD *thd=current_thd;
   User_level_lock *ull;
   int error;
+  Interruptible_wait timed_cond(thd);
   DBUG_ENTER("Item_func_get_lock::val_int");
 
   /*
@@ -3812,11 +3857,13 @@ longlong Item_func_get_lock::val_int()
   thd->mysys_var->current_mutex= &LOCK_user_locks;
   thd->mysys_var->current_cond=  &ull->cond;
 
+  timed_cond.set_timeout(timeout * ULL(1000000000));
+
   error= 0;
   while (ull->locked && !thd->killed)
   {
     DBUG_PRINT("info", ("waiting on lock"));
-    error= interruptible_wait(thd, &ull->cond, &LOCK_user_locks, timeout);
+    error= timed_cond.wait(&ull->cond, &LOCK_user_locks);
     if (error == ETIMEDOUT || error == ETIME)
     {
       DBUG_PRINT("info", ("lock wait timeout"));
@@ -4011,6 +4058,7 @@ void Item_func_benchmark::print(String *
 longlong Item_func_sleep::val_int()
 {
   THD *thd= current_thd;
+  Interruptible_wait timed_cond(thd);
   mysql_cond_t cond;
   double timeout;
   int error;
@@ -4030,6 +4078,8 @@ longlong Item_func_sleep::val_int()
   if (timeout < 0.00001)
     return 0;
 
+  timed_cond.set_timeout((ulonglong) (timeout * 1000000000.0));
+
   mysql_cond_init(key_item_func_sleep_cond, &cond, NULL);
   mysql_mutex_lock(&LOCK_user_locks);
 
@@ -4040,7 +4090,7 @@ longlong Item_func_sleep::val_int()
   error= 0;
   while (!thd->killed)
   {
-    error= interruptible_wait(thd, &cond, &LOCK_user_locks, timeout);
+    error= timed_cond.wait(&cond, &LOCK_user_locks);
     if (error == ETIMEDOUT || error == ETIME)
       break;
     error= 0;


Attachment: [text/bzr-bundle] bzr/alexander.nozdrin@oracle.com-20101014101200-aaz2pstq1af5gn8l.bundle
Thread
bzr push into mysql-trunk-merge branch (alexander.nozdrin:3269 to 3270) Alexander Nozdrin14 Oct