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

Assertion `i >= 0' failed on setting default_tmp_storage_engine to 'DEFAULT' in 10.7

Details

    Description

      SET GLOBAL default_tmp_storage_engine='DEFAULT';
      

      Leads to:

      10.7.0 71ed8c136fa203b9b3a678a6d5cc72235ef73ef7 (Debug)

      mysqld: /test/10.7_dbg/sql/sql_plugin.cc:1385: void intern_plugin_unlock(LEX*, plugin_ref): Assertion `i >= 0' failed.
      

      10.7.0 71ed8c136fa203b9b3a678a6d5cc72235ef73ef7 (Debug)

      Core was generated by `/test/MD200721-mariadb-10.7.0-linux-x86_64-dbg/bin/mysqld --no-defaults --core-'.
      Program terminated with signal SIGABRT, Aborted.
      #0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
      [Current thread is 1 (Thread 0x14eb3c63b700 (LWP 263804))]
      (gdb) bt
      #0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
      #1  0x000014eb3da9f859 in __GI_abort () at abort.c:79
      #2  0x000014eb3da9f729 in __assert_fail_base (fmt=0x14eb3dc35588 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x559e49106b96 "i >= 0", file=0x559e49107380 "/test/10.7_dbg/sql/sql_plugin.cc", line=1385, function=<optimized out>) at assert.c:92
      #3  0x000014eb3dab0f36 in __GI___assert_fail (assertion=assertion@entry=0x559e49106b96 "i >= 0", file=file@entry=0x559e49107380 "/test/10.7_dbg/sql/sql_plugin.cc", line=line@entry=1385, function=function@entry=0x559e49107568 "void intern_plugin_unlock(LEX*, plugin_ref)") at assert.c:101
      #4  0x0000559e484a1417 in intern_plugin_unlock (lex=lex@entry=0x14eae4005068, plugin=plugin@entry=0x14eae4013a18) at /test/10.7_dbg/sql/sql_plugin.cc:1385
      #5  0x0000559e484a551e in plugin_unlock (thd=thd@entry=0x14eae4000db8, plugin=plugin@entry=0x14eae4013a18) at /test/10.7_dbg/sql/sql_plugin.cc:1413
      #6  0x0000559e48614faa in check_engine_supports_temporary (self=<optimized out>, thd=0x14eae4000db8, var=<optimized out>) at /test/10.7_dbg/sql/sys_vars.cc:763
      #7  0x0000559e48384c60 in sys_var::check (this=0x559e49a6cae0 <Sys_default_tmp_storage_engine>, thd=thd@entry=0x14eae4000db8, var=var@entry=0x14eae4013f58) at /test/10.7_dbg/sql/set_var.cc:246
      #8  0x0000559e48385c94 in set_var::check (this=0x14eae4013f58, thd=0x14eae4000db8) at /test/10.7_dbg/sql/set_var.cc:810
      #9  0x0000559e483863a4 in sql_set_variables (thd=thd@entry=0x14eae4000db8, var_list=var_list@entry=0x14eae4006038, free=free@entry=true) at /test/10.7_dbg/sql/set_var.cc:738
      #10 0x0000559e4848a821 in mysql_execute_command (thd=thd@entry=0x14eae4000db8, is_called_from_prepared_stmt=is_called_from_prepared_stmt@entry=false) at /test/10.7_dbg/sql/sql_parse.cc:5037
      #11 0x0000559e48473ead in mysql_parse (thd=thd@entry=0x14eae4000db8, rawbuf=<optimized out>, length=<optimized out>, parser_state=parser_state@entry=0x14eb3c63a400) at /test/10.7_dbg/sql/sql_parse.cc:8026
      #12 0x0000559e484829f8 in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x14eae4000db8, packet=packet@entry=0x14eae400b749 "SET GLOBAL default_tmp_storage_engine='DEFAULT'", packet_length=packet_length@entry=47, blocking=blocking@entry=true) at /test/10.7_dbg/sql/sql_class.h:1340
      #13 0x0000559e48485e05 in do_command (thd=0x14eae4000db8, blocking=blocking@entry=true) at /test/10.7_dbg/sql/sql_parse.cc:1404
      #14 0x0000559e485fbf48 in do_handle_one_connection (connect=<optimized out>, connect@entry=0x559e4c7d3a98, put_in_cache=put_in_cache@entry=true) at /test/10.7_dbg/sql/sql_connect.cc:1410
      #15 0x0000559e485fc54d in handle_one_connection (arg=arg@entry=0x559e4c7d3a98) at /test/10.7_dbg/sql/sql_connect.cc:1312
      #16 0x0000559e48a645b2 in pfs_spawn_thread (arg=0x559e4c6fca48) at /test/10.7_dbg/storage/perfschema/pfs.cc:2201
      #17 0x000014eb3dfae609 in start_thread (arg=<optimized out>) at pthread_create.c:477
      #18 0x000014eb3db9c293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
      

      10.6.4 (and 10.6.3 @ 891a927e804c5a3a582f6137c2f316ef7abb25ca as well) do not fail:

      10.6.4 42b9daaea7ece6155558f7c3bf638e8e175a7ff7 (Debug)

      10.6.4-dbg>SET GLOBAL default_tmp_storage_engine='DEFAULT';
      Query OK, 0 rows affected (0.000 sec)
       
      10.6.4-dbg>SELECT @@GLOBAL.default_tmp_storage_engine;
      +-------------------------------------+
      | @@GLOBAL.default_tmp_storage_engine |
      +-------------------------------------+
      | InnoDB                              |
      +-------------------------------------+
      1 row in set (0.000 sec)
      

      Setting it directly to InnoDB does not fail:

      10.7.0 71ed8c136fa203b9b3a678a6d5cc72235ef73ef7 (Debug)

      10.7.0-dbg>SET GLOBAL default_tmp_storage_engine='InnoDB';
      Query OK, 0 rows affected (0.000 sec)
      

      10.7 Optimized build does not fail:

      10.7.0 71ed8c136fa203b9b3a678a6d5cc72235ef73ef7 (Optimized)

      10.7.0-opt>SET GLOBAL default_tmp_storage_engine='DEFAULT';
      Query OK, 0 rows affected (0.000 sec)
      

      Confirmed that InnoDB is correctly listed as DEFAULT in 10.7:

      10.7.0 71ed8c136fa203b9b3a678a6d5cc72235ef73ef7 (Debug)

      10.7.0-dbg>show engines;
      +--------------------+---------+-------------------------------------------------------------------------------------------------+--------------+------+------------+
      | Engine             | Support | Comment                                                                                         | Transactions | XA   | Savepoints |
      +--------------------+---------+-------------------------------------------------------------------------------------------------+--------------+------+------------+
      | CSV                | YES     | Stores tables as CSV files                                                                      | NO           | NO   | NO         |
      | MRG_MyISAM         | YES     | Collection of identical MyISAM tables                                                           | NO           | NO   | NO         |
      | MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables                                       | NO           | NO   | NO         |
      | Aria               | YES     | Crash-safe tables with MyISAM heritage. Used for internal temporary tables and privilege tables | NO           | NO   | NO         |
      | MyISAM             | YES     | Non-transactional engine with good performance and small data footprint                         | NO           | NO   | NO         |
      | SEQUENCE           | YES     | Generated tables filled with sequential values                                                  | YES          | NO   | YES        |
      | InnoDB             | DEFAULT | Supports transactions, row-level locking, foreign keys and encryption for tables                | YES          | YES  | YES        |
      | PERFORMANCE_SCHEMA | YES     | Performance Schema                                                                              | NO           | NO   | NO         |
      +--------------------+---------+-------------------------------------------------------------------------------------------------+--------------+------+------------+
      8 rows in set (0.001 sec)
      

      Bug confirmed present in:
      MariaDB: 10.7.0 (dbg)

      Bug (or feature/syntax) confirmed not present in:
      MariaDB: 10.2.39 (dbg), 10.2.39 (opt), 10.3.30 (dbg), 10.3.30 (opt), 10.4.20 (dbg), 10.4.20 (opt), 10.5.11 (dbg), 10.5.11 (opt), 10.6.4 (dbg), 10.6.4 (opt), 10.7.0 (opt)
      MySQL: 5.5.62 (dbg), 5.5.62 (opt), 5.6.51 (dbg), 5.6.51 (opt), 5.7.34 (dbg), 5.7.34 (opt), 8.0.24 (dbg), 8.0.24 (opt)

      Attachments

        Issue Links

          Activity

            After quick search:
            Culprit check_engine_supports_temporary() with plugin_ref is exposing that is wrong allocated memory. Note that hton is valid.

            (gdb) f 6
            +f 6
            #6  0x000055555604e83b in check_engine_supports_temporary (self=0x5555579d77c0 <Sys_default_tmp_storage_engine>, thd=0x7fffd4000d78, var=0x7fffd4017e78) at /home/anel/mariadb/10.7/sql/sys_vars.cc:763
            763	  plugin_unlock(thd, plugin);
            (gdb) p *var
            +p *var
            $25 = {
              <set_var_base> = {
                <Sql_alloc> = {<No data fields>}, 
                members of set_var_base:
                _vptr.set_var_base = 0x555557664ff0 <vtable for set_var+16>
              }, 
              members of set_var:
              var = 0x5555579d77c0 <Sys_default_tmp_storage_engine>,
              value = 0x7fffd4017dd0,
              type = SHOW_OPT_GLOBAL,
              save_result = {
                ulonglong_value = 140736750201640,
                longlong_value = 140736750201640,
                double_value = 6.9533193381971451e-310,
                plugin = 0x7fffd400ab28,
                plugins = 0x7fffd400ab28,
                time_zone = 0x7fffd400ab28,
                string_value = {
                  str = 0x7fffd400ab28 "\217\217\217\217\217\217\217\217\240",
                  length = 11936128518282651045
                },
                ptr = 0x7fffd400ab28
              },
              base = {
                str = 0x0,
                length = 0
              }
            }
             
             
            (gdb) p var->save_result->plugins 
            +p var->save_result->plugins
            $22 = (plugin_ref *) 0x7fffd400ab28
            (gdb) p *var->save_result->plugins
            +p *var->save_result->plugins
            $23 = (plugin_ref) 0x8f8f8f8f8f8f8f8f
             
            (gdb) p *(*var->save_result->plugins)
            +p *(*var->save_result->plugins)
            Cannot access memory at address 0x8f8f8f8f8f8f8f8f
            

            After that intern_plugin_unlock () is checking for lex struct obtained from thd->lex where plugins.elements = 0 :

            (gdb) f 4
            +f 4
            #4  0x0000555555e988c3 in intern_plugin_unlock (lex=0x7fffd4005028, plugin=0x7fffd400ab28) at /home/anel/mariadb/10.7/sql/sql_plugin.cc:1385
             
             
            │   1372          if (lex)                                                                                                                                                                                                                                                        │
            │   1373          {                                                                                                                                                                                                                                                               │
            │   1374            /*                                                                                                                                                                                                                                                            │
            │   1375              Remove one instance of this plugin from the use list.                                                                                                                                                                                                       │
            │   1376              We are searching backwards so that plugins locked last                                                                                                                                                                                                      │
            │   1377              could be unlocked faster - optimizing for LIFO semantics.                                                                                                                                                                                                   │
            │   1378            */                                                                                                                                                                                                                                                            │
            │   1379            for (i= lex->plugins.elements - 1; i >= 0; i--)                                                                                                                                                                                                               │
            │   1380              if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*))                                                                                                                                                                                              │
            │   1381              {                                                                                                                                                                                                                                                           │
            │   1382                delete_dynamic_element(&lex->plugins, i);                                                                                                                                                                                                                 │
            │   1383                break;                                                                                                                                                                                                                                                    │
            │   1384              }                                                                                                                                                                                                                                                           │
            │  >1385            DBUG_ASSERT(i >= 0);                                                                                                                                                                                                                                          │
            │   1386          }  
             
            (gdb) p lex->plugins.elements 
            +p lex->plugins.elements
            $26 = 0
            

            In the same function plugin_ref_to_int is valid:

             
                pi= plugin_ref_to_int(plugin);
             
             
            (gdb) p pi
            +p pi
            $27 = (st_plugin_int *) 0x5555583ed840
            (gdb) p pi->
            data         load_option  locks_total  mem_root     name         nbackups     plugin       plugin_dl    ptr_backup   ref_count    state        system_vars
            (gdb) p pi->name 
            +p pi->name
            $28 = {
              str = 0x5555570460f4 "MyISAM",
              length = 6
            
            

            anel Anel Husakovic added a comment - After quick search: Culprit check_engine_supports_temporary() with plugin_ref is exposing that is wrong allocated memory. Note that hton is valid. (gdb) f 6 +f 6 #6 0x000055555604e83b in check_engine_supports_temporary (self=0x5555579d77c0 <Sys_default_tmp_storage_engine>, thd=0x7fffd4000d78, var=0x7fffd4017e78) at /home/anel/mariadb/10.7/sql/sys_vars.cc:763 763 plugin_unlock(thd, plugin); (gdb) p *var +p *var $25 = { <set_var_base> = { <Sql_alloc> = {<No data fields>}, members of set_var_base: _vptr.set_var_base = 0x555557664ff0 <vtable for set_var+16> }, members of set_var: var = 0x5555579d77c0 <Sys_default_tmp_storage_engine>, value = 0x7fffd4017dd0, type = SHOW_OPT_GLOBAL, save_result = { ulonglong_value = 140736750201640, longlong_value = 140736750201640, double_value = 6.9533193381971451e-310, plugin = 0x7fffd400ab28, plugins = 0x7fffd400ab28, time_zone = 0x7fffd400ab28, string_value = { str = 0x7fffd400ab28 "\217\217\217\217\217\217\217\217\240", length = 11936128518282651045 }, ptr = 0x7fffd400ab28 }, base = { str = 0x0, length = 0 } }     (gdb) p var->save_result->plugins +p var->save_result->plugins $22 = (plugin_ref *) 0x7fffd400ab28 (gdb) p *var->save_result->plugins +p *var->save_result->plugins $23 = (plugin_ref) 0x8f8f8f8f8f8f8f8f   (gdb) p *(*var->save_result->plugins) +p *(*var->save_result->plugins) Cannot access memory at address 0x8f8f8f8f8f8f8f8f After that intern_plugin_unlock () is checking for lex struct obtained from thd->lex where plugins.elements = 0 : (gdb) f 4 +f 4 #4 0x0000555555e988c3 in intern_plugin_unlock (lex=0x7fffd4005028, plugin=0x7fffd400ab28) at /home/anel/mariadb/10.7/sql/sql_plugin.cc:1385     │ 1372 if (lex) │ │ 1373 { │ │ 1374 /* │ │ 1375 Remove one instance of this plugin from the use list. │ │ 1376 We are searching backwards so that plugins locked last │ │ 1377 could be unlocked faster - optimizing for LIFO semantics. │ │ 1378 */ │ │ 1379 for (i= lex->plugins.elements - 1; i >= 0; i--) │ │ 1380 if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*)) │ │ 1381 { │ │ 1382 delete_dynamic_element(&lex->plugins, i); │ │ 1383 break; │ │ 1384 } │ │ >1385 DBUG_ASSERT(i >= 0); │ │ 1386 }   (gdb) p lex->plugins.elements +p lex->plugins.elements $26 = 0 In the same function plugin_ref_to_int is valid:   pi= plugin_ref_to_int(plugin);     (gdb) p pi +p pi $27 = (st_plugin_int *) 0x5555583ed840 (gdb) p pi-> data load_option locks_total mem_root name nbackups plugin plugin_dl ptr_backup ref_count state system_vars (gdb) p pi->name +p pi->name $28 = { str = 0x5555570460f4 "MyISAM", length = 6

            Seems we are expecting to have NULL value in case when SET ... = DEFAULT (commit a8caad316a89, I guess comment is wrong) in set_var::check() but we don't end with NULL value.

            │   789           /* value is a NULL pointer if we are using SET ... = DEFAULT */                                                                                                                                                                                                 │
            │   790           if (!value)                                                                                                                                                                                                                                                     │
            │   791             return 0; 
            

            Debugging:

            Thread 6 "mariadbd" hit Breakpoint 1, set_var::check (this=0x7fffd4017e78, thd=0x7fffd4000d78) at /home/anel/mariadb/10.7/sql/set_var.cc:775
            warning: Source file is more recent than executable.
            775	  var->do_deprecated_warning(thd);
            (gdb) p value
            +p value
            $11 = (Item *) 0x7fffd4017dd0
            (gdb) p *value
            +p *value
            $12 = {
              <Value_source> = {<No data fields>}, 
              <Type_all_attributes> = {
                <Type_std_attributes> = {
                  <Type_numeric_attributes> = {
                    max_length = 7,
                    decimals = 39,
                    unsigned_flag = false
                  }, 
                  members of Type_std_attributes:
                  collation = {
                    collation = 0x55555789a580 <my_charset_latin1>,
                    derivation = DERIVATION_COERCIBLE,
                    repertoire = MY_REPERTOIRE_ASCII
                  }
                }, 
                members of Type_all_attributes:
                _vptr.Type_all_attributes = 0x5555576df108 <vtable for Item_string+16>
              }, 
              members of Item:
              next = 0x0,
              str_value = {
                <Charset> = {
                  m_charset = 0x55555789a580 <my_charset_latin1>
                }, 
                <Binary_string> = {
                  <Sql_alloc> = {<No data fields>}, 
                  members of Binary_string:
                  Ptr = 0x7fffd4017dc8 "DEFAULT",
                  str_length = 7,
                  Alloced_length = 0,
                  extra_alloc = 0,
                  alloced = false,
                  thread_specific = false
                }, <No data fields>},
              name = {
                str = 0x7fffd4017e40 "DEFAULT",
                length = 7
              },
              orig_name = 0x0,
              base_flags = item_base_t::FIXED,
              with_flags = item_with_t::NONE,
              marker = 0,
              null_value = false,
              is_expensive_cache = -1 '\377',
              join_tab_idx = 61 '='
            }
            
            

            So thd->lex->plugins.elements =0 although plugin is read correclty.

            sanja where are thd->lex->plugins are populated, so I can put breakpoint to observe?

            anel Anel Husakovic added a comment - Seems we are expecting to have NULL value in case when SET ... = DEFAULT (commit a8caad316a89, I guess comment is wrong) in set_var::check() but we don't end with NULL value. │ 789 /* value is a NULL pointer if we are using SET ... = DEFAULT */ │ │ 790 if (!value) │ │ 791 return 0; Debugging: Thread 6 "mariadbd" hit Breakpoint 1, set_var::check (this=0x7fffd4017e78, thd=0x7fffd4000d78) at /home/anel/mariadb/10.7/sql/set_var.cc:775 warning: Source file is more recent than executable. 775 var->do_deprecated_warning(thd); (gdb) p value +p value $11 = (Item *) 0x7fffd4017dd0 (gdb) p *value +p *value $12 = { <Value_source> = {<No data fields>}, <Type_all_attributes> = { <Type_std_attributes> = { <Type_numeric_attributes> = { max_length = 7, decimals = 39, unsigned_flag = false }, members of Type_std_attributes: collation = { collation = 0x55555789a580 <my_charset_latin1>, derivation = DERIVATION_COERCIBLE, repertoire = MY_REPERTOIRE_ASCII } }, members of Type_all_attributes: _vptr.Type_all_attributes = 0x5555576df108 <vtable for Item_string+16> }, members of Item: next = 0x0, str_value = { <Charset> = { m_charset = 0x55555789a580 <my_charset_latin1> }, <Binary_string> = { <Sql_alloc> = {<No data fields>}, members of Binary_string: Ptr = 0x7fffd4017dc8 "DEFAULT", str_length = 7, Alloced_length = 0, extra_alloc = 0, alloced = false, thread_specific = false }, <No data fields>}, name = { str = 0x7fffd4017e40 "DEFAULT", length = 7 }, orig_name = 0x0, base_flags = item_base_t::FIXED, with_flags = item_with_t::NONE, marker = 0, null_value = false, is_expensive_cache = -1 '\377', join_tab_idx = 61 '=' } So thd->lex->plugins.elements =0 although plugin is read correclty. sanja where are thd->lex->plugins are populated, so I can put breakpoint to observe?

            I made grep for plugins, and search for lex, here is the result

                if (lex)
                  insert_dynamic(&lex->plugins, (uchar*)&plugin);
            

            in sql_plugin.cc .

            All above is just 5 min search, I have no idea how lex->plugins work, but I think the guess is correct

            sanja Oleksandr Byelkin added a comment - I made grep for plugins, and search for lex, here is the result if (lex) insert_dynamic(&lex->plugins, (uchar*)&plugin); in sql_plugin.cc . All above is just 5 min search, I have no idea how lex->plugins work, but I think the guess is correct

            cvicentiu can you please review 31d9c60a06d1

            anel Anel Husakovic added a comment - cvicentiu can you please review 31d9c60a06d1

            1. why setting the value to default even invokes the check function at all?
            2. what if default_tmp_storage_engine is set to an invalid plugin, like "foo" ?
            3. what if default_tmp_storage_engine is set to a valid plugin, but not a storage engine, like "unix_socket"?

            serg Sergei Golubchik added a comment - 1. why setting the value to default even invokes the check function at all? 2. what if default_tmp_storage_engine is set to an invalid plugin, like "foo" ? 3. what if default_tmp_storage_engine is set to a valid plugin, but not a storage engine, like "unix_socket"?

            serg
            1. Because the value is 'default' not default. It's an Item_string that needs to be evaluated.
            2, 3. The type of the variable default_tmp_storage_engine is a Sys_var_plugin and it's also marked as a MYSQL_STORAGE_ENGINE_PLUGIN.
            Its do_check method already checks for the existence of the plugin.

            I've written below an analysis of the root cause for the bug and also the fix:

            The bug actually comes from an assumption that ha_resolve_by_name will lock the plugin when resolving it. This is not the case if the name actually is "DEFAULT". See

               if (thd && !my_charset_latin1.strnncoll(                                                                                
                            (const uchar *)name->str, name->length,                                                        
                            (const uchar *)STRING_WITH_LEN("DEFAULT"), 0))                                                 
                 return tmp_table ?  ha_default_tmp_plugin(thd) : ha_default_plugin(thd);   
            

            ha_default_tmp_plugin will not lock it if the session thd variable is set.

             208 static plugin_ref ha_default_tmp_plugin(THD *thd)                                                                         
             209 {                                                                                                                         
             210   if (thd->variables.tmp_table_plugin)                                                                                    
             211     return thd->variables.tmp_table_plugin;                                                                               
             212   if (global_system_variables.tmp_table_plugin)                                                                           
             213     return my_plugin_lock(thd, global_system_variables.tmp_table_plugin);                                                 
             214   return ha_default_plugin(thd);                                                                                          
             215 }     
            

            Nonetheless, the initial code was wrong in that it tried to lock the plugin in the first place, in order to get access to the handlerton. We already have the plugin locked in var->save_result.plugin from the Sys_var_plugin's do_check method. All we need to do is evaluate that the plugin supports temporary tables.

            The default_tmp_storage_engine check code now becomes:

             static bool check_engine_supports_temporary(sys_var *self, THD *thd, set_var *var)
             {
            -  String str, *res;
            -  LEX_CSTRING name;
            -  if (!var->value || var->value->is_null())
            +  plugin_ref plugin= var->save_result.plugin;
            +  if (!plugin)
                 return false;
            -  res= var->value->val_str(&str);
            -  res->get_value(&name);
            -  plugin_ref plugin= ha_resolve_by_name(thd, &name, true);
               DBUG_ASSERT(plugin);
               handlerton *hton= plugin_hton(plugin);
               DBUG_ASSERT(hton);
               if (ha_check_storage_engine_flag(hton, HTON_TEMPORARY_NOT_SUPPORTED))
               {
                 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), hton_name(hton)->str,
                          "TEMPORARY");
            -    plugin_unlock(thd, plugin);
                 return true;
               }
            -  plugin_unlock(thd, plugin);
               return false;
             }
            

            cvicentiu Vicențiu Ciorbaru added a comment - serg 1. Because the value is 'default' not default . It's an Item_string that needs to be evaluated. 2, 3. The type of the variable default_tmp_storage_engine is a Sys_var_plugin and it's also marked as a MYSQL_STORAGE_ENGINE_PLUGIN . Its do_check method already checks for the existence of the plugin. I've written below an analysis of the root cause for the bug and also the fix: The bug actually comes from an assumption that ha_resolve_by_name will lock the plugin when resolving it. This is not the case if the name actually is "DEFAULT". See if (thd && !my_charset_latin1.strnncoll( (const uchar *)name->str, name->length, (const uchar *)STRING_WITH_LEN("DEFAULT"), 0)) return tmp_table ? ha_default_tmp_plugin(thd) : ha_default_plugin(thd); ha_default_tmp_plugin will not lock it if the session thd variable is set. 208 static plugin_ref ha_default_tmp_plugin(THD *thd) 209 { 210 if (thd->variables.tmp_table_plugin) 211 return thd->variables.tmp_table_plugin; 212 if (global_system_variables.tmp_table_plugin) 213 return my_plugin_lock(thd, global_system_variables.tmp_table_plugin); 214 return ha_default_plugin(thd); 215 } Nonetheless, the initial code was wrong in that it tried to lock the plugin in the first place, in order to get access to the handlerton. We already have the plugin locked in var->save_result.plugin from the Sys_var_plugin's do_check method. All we need to do is evaluate that the plugin supports temporary tables. The default_tmp_storage_engine check code now becomes: static bool check_engine_supports_temporary(sys_var *self, THD *thd, set_var *var) { - String str, *res; - LEX_CSTRING name; - if (!var->value || var->value->is_null()) + plugin_ref plugin= var->save_result.plugin; + if (!plugin) return false; - res= var->value->val_str(&str); - res->get_value(&name); - plugin_ref plugin= ha_resolve_by_name(thd, &name, true); DBUG_ASSERT(plugin); handlerton *hton= plugin_hton(plugin); DBUG_ASSERT(hton); if (ha_check_storage_engine_flag(hton, HTON_TEMPORARY_NOT_SUPPORTED)) { my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), hton_name(hton)->str, "TEMPORARY"); - plugin_unlock(thd, plugin); return true; } - plugin_unlock(thd, plugin); return false; }

            People

              cvicentiu Vicențiu Ciorbaru
              Roel Roel Van de Paar
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.