Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-6774

Deadlock between SELECT, DROP TABLE, SHOW STATUS and SET @@global.log_output

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 5.5.39
    • Fix Version/s: 5.5.40
    • Component/s: OTHER
    • Labels:
      None

      Description

      Deadlock chain:

      rdlock(LOCK_logger)                -> lock(LOCK_open)                    SELECT 1
      lock(LOCK_open)                    -> lock(LOCK_status)                  DROP TABLE t1
      lock(LOCK_status)                  -> lock(LOCK_global_system_variables) SHOW STATUS
      lock(LOCK_global_system_variables) -> wrlock(LOCK_logger)                SET @@global.log_output=DEFAULT
      

      MTR test to reproduce this deadlock:

      --source include/have_example_plugin.inc
      
      SET @@global.log_output='TABLE';
      INSTALL SONAME 'ha_example';
      CREATE TABLE t1(a int) ENGINE=EXAMPLE;
      SELECT * FROM t1;
      UNINSTALL SONAME 'ha_example';
      
      connect(con1, localhost, root,,);
      connect(con2, localhost, root,,);
      connect(con3, localhost, root,,);
      
      connection con1;
      SET debug_sync='fix_log_output SIGNAL ready WAIT_FOR go';
      send SET @@global.log_output=DEFAULT;
      
      connection con2;
      SET debug_sync='now WAIT_FOR ready';
      SET debug_sync='fill_status SIGNAL ready';
      send SHOW STATUS LIKE 'slave_open_temp_tables';
      
      connection con3;
      SET debug_sync='now WAIT_FOR ready';
      SET debug_sync='remove_status_vars SIGNAL ready';
      send DROP TABLE t1;
      
      connection default;
      SELECT 1;
      
      connection con1;
      reap;
      disconnect con1;
      
      connection con2;
      reap;
      disconnect con2;
      
      connection con3;
      reap;
      disconnect con3;
      
      connection default;
      SET debug_sync='RESET';
      

      Debug sync points:

      === modified file 'sql/log.cc'
      --- sql/log.cc	2014-08-02 19:26:16 +0000
      +++ sql/log.cc	2014-09-24 11:02:19 +0000
      @@ -600,6 +600,11 @@ void Log_to_csv_event_handler::cleanup()
         ulonglong save_thd_options;
         bool save_time_zone_used;
         DBUG_ENTER("log_general");
      +  if (!strncmp(sql_text, "SELECT 1", sql_text_len))
      +  {
      +    debug_sync_set_action(thd, STRING_WITH_LEN("now WAIT_FOR ready"));
      +    debug_sync_set_action(thd, STRING_WITH_LEN("now SIGNAL go"));
      +  }
      
         /*
           CSV uses TIME_to_timestamp() internally if table needs to be repaired
      
      === modified file 'sql/sql_show.cc'
      --- sql/sql_show.cc	2014-09-12 06:41:35 +0000
      +++ sql/sql_show.cc	2014-09-24 09:58:42 +0000
      @@ -2543,6 +2543,7 @@ void remove_status_vars(SHOW_VAR *list)
       {
         if (status_vars_inited)
         {
      +    DEBUG_SYNC(current_thd, "remove_status_vars");
           mysql_mutex_lock(&LOCK_status);
           SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
      
      @@ -6986,6 +6987,7 @@ int fill_status(THD *thd, TABLE_LIST *ta
           partial_cond->val_int();
      
         mysql_mutex_lock(&LOCK_status);
      +  DEBUG_SYNC(thd, "fill_status");
         if (option_type == OPT_GLOBAL)
           calc_sum_of_all_status(&tmp);
         res= show_status_array(thd, wild,
      
      === modified file 'sql/sys_vars.cc'
      --- sql/sys_vars.cc	2014-08-02 19:26:16 +0000
      +++ sql/sys_vars.cc	2014-09-24 10:48:38 +0000
      @@ -3246,6 +3246,7 @@ static bool check_not_empty_set(sys_var
       }
       static bool fix_log_output(sys_var *self, THD *thd, enum_var_type type)
       {
      +  DEBUG_SYNC(thd, "fix_log_output");
         logger.lock_exclusive();
         logger.init_slow_log(log_output_options);
         logger.init_general_log(log_output_options);
      
      

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

              Hide
              svoj Sergey Vojtovich added a comment -

              Sergei, please review fix for this bug.

              Show
              svoj Sergey Vojtovich added a comment - Sergei, please review fix for this bug.
              Hide
              serg Sergei Golubchik added a comment -

              ok to push, thanks

              Show
              serg Sergei Golubchik added a comment - ok to push, thanks
              Hide
              svoj Sergey Vojtovich added a comment -

              Fixed in 5.5.40:

              revno: 4297
              revision-id: svoj@mariadb.org-20140925064311-lq46fqxnnwyfliu5
              parent: svoj@mariadb.org-20140918154506-24bkasfcnmww3w03
              committer: Sergey Vojtovich <svoj@mariadb.org>
              branch nick: 5.5
              timestamp: Thu 2014-09-25 10:43:11 +0400
              message:
                MDEV-6774 - Deadlock between SELECT, DROP TABLE, SHOW STATUS and
                            SET @@global.log_output
              
                Deadlock chain:
                rdlock(LOCK_logger) -> lock(LOCK_open)     SELECT 1
                lock(LOCK_open)     -> lock(LOCK_status)   DROP TABLE t1
                lock(LOCK_status)   -> lock(LOCK_g_s_v)    SHOW STATUS
                lock(LOCK_g_s_)     -> wrlock(LOCK_logger) SET @@global.log_output=DEFAULT
              
                Fixed by removing relationship between LOCK_status and
                LOCK_global_system_variables during SHOW STATUS: we don't really need
                LOCK_global_system_variables when accessing status vars.
              
              Show
              svoj Sergey Vojtovich added a comment - Fixed in 5.5.40: revno: 4297 revision-id: svoj@mariadb.org-20140925064311-lq46fqxnnwyfliu5 parent: svoj@mariadb.org-20140918154506-24bkasfcnmww3w03 committer: Sergey Vojtovich <svoj@mariadb.org> branch nick: 5.5 timestamp: Thu 2014-09-25 10:43:11 +0400 message: MDEV-6774 - Deadlock between SELECT, DROP TABLE, SHOW STATUS and SET @@global.log_output Deadlock chain: rdlock(LOCK_logger) -> lock(LOCK_open) SELECT 1 lock(LOCK_open) -> lock(LOCK_status) DROP TABLE t1 lock(LOCK_status) -> lock(LOCK_g_s_v) SHOW STATUS lock(LOCK_g_s_) -> wrlock(LOCK_logger) SET @@global.log_output=DEFAULT Fixed by removing relationship between LOCK_status and LOCK_global_system_variables during SHOW STATUS: we don't really need LOCK_global_system_variables when accessing status vars.

                People

                • Assignee:
                  svoj Sergey Vojtovich
                  Reporter:
                  svoj Sergey Vojtovich
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  2 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved:

                    Time Tracking

                    Estimated:
                    Original Estimate - Not Specified
                    Not Specified
                    Remaining:
                    Remaining Estimate - 0 minutes
                    0m
                    Logged:
                    Time Spent - 5 minutes
                    5m