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

Server crashes in GetTypeID / ha_connect::GetRealType upon altering table engine

Details

    Description

      --source include/have_innodb.inc
       
      INSTALL SONAME 'ha_connect';
       
      CREATE TABLE t (f INT) ENGINE=CONNECT;
      ALTER TABLE t ENGINE InnoDB;
       
      # Cleanup
      DROP TABLE t;
      UNINSTALL SONAME 'ha_connect';
      

      10.5 6bb3949e

      #3  <signal handler called>
      #4  __strcasecmp_l_avx () at ../sysdeps/x86_64/multiarch/strcmp-sse42.S:270
      #5  0x00007fa2ad4da34d in GetTypeID (type=0xa5a5a5a5a5a5a500 <error: Cannot access memory at address 0xa5a5a5a5a5a5a500>) at /data/src/10.5/storage/connect/mycat.cc:125
      #6  0x00007fa2ad4bf274 in ha_connect::GetRealType (this=0x7fa288016428, pos=0x7fa2881aea28) at /data/src/10.5/storage/connect/ha_connect.cc:1056
      #7  0x00007fa2ad4ca002 in ha_connect::check_privileges (this=0x7fa288016428, thd=0x7fa288000db8, options=0x7fa2881aea28, dbn=0x7fa2bcc4a560 "test", quick=false) at /data/src/10.5/storage/connect/ha_connect.cc:4479
      #8  0x00007fa2ad4cbb85 in ha_connect::delete_or_rename_table (this=0x7fa288016428, name=0x7fa2bcc4b4e0 "./test/t", to=0x0) at /data/src/10.5/storage/connect/ha_connect.cc:5216
      #9  0x00007fa2ad4cbd2c in ha_connect::delete_table (this=0x7fa288016428, name=0x7fa2bcc4b4e0 "./test/t") at /data/src/10.5/storage/connect/ha_connect.cc:5245
      #10 0x000055757c8e763d in hton_drop_table (hton=0x7fa2881b3ca8, path=0x7fa2bcc4b4e0 "./test/t") at /data/src/10.5/sql/handler.cc:564
      #11 0x000055757c8ecd71 in ha_delete_table (thd=0x7fa288000db8, hton=0x7fa2881b3ca8, path=0x7fa2bcc4b4e0 "./test/t", db=0x7fa2bcc4c820, alias=0x7fa2bcc4c830, generate_warning=false) at /data/src/10.5/sql/handler.cc:2770
      #12 0x000055757c66fd14 in quick_rm_table (thd=0x7fa288000db8, base=0x7fa2881b3ca8, db=0x7fa2bcc4c820, table_name=0x7fa2bcc4c830, flags=4, table_path=0x0) at /data/src/10.5/sql/sql_table.cc:2884
      #13 0x000055757c687be5 in mysql_alter_table (thd=0x7fa288000db8, new_db=0x7fa288005800, new_name=0x7fa288005c00, create_info=0x7fa2bcc4d420, table_list=0x7fa288014018, alter_info=0x7fa2bcc4d350, order_num=0, order=0x0, ignore=false, if_exists=false) at /data/src/10.5/sql/sql_table.cc:11014
      #14 0x000055757c72ea94 in Sql_cmd_alter_table::execute (this=0x7fa2880146f8, thd=0x7fa288000db8) at /data/src/10.5/sql/sql_alter.cc:539
      #15 0x000055757c5859cc in mysql_execute_command (thd=0x7fa288000db8) at /data/src/10.5/sql/sql_parse.cc:6006
      #16 0x000055757c58bd88 in mysql_parse (thd=0x7fa288000db8, rawbuf=0x7fa288013f30 "ALTER TABLE t ENGINE InnoDB", length=27, parser_state=0x7fa2bcc4e510, is_com_multi=false, is_next_command=false) at /data/src/10.5/sql/sql_parse.cc:8042
      #17 0x000055757c577d6b in dispatch_command (command=COM_QUERY, thd=0x7fa288000db8, packet=0x7fa2880090a9 "", packet_length=27, is_com_multi=false, is_next_command=false) at /data/src/10.5/sql/sql_parse.cc:1872
      #18 0x000055757c57655f in do_command (thd=0x7fa288000db8) at /data/src/10.5/sql/sql_parse.cc:1353
      #19 0x000055757c723e57 in do_handle_one_connection (connect=0x55757f167608, put_in_cache=true) at /data/src/10.5/sql/sql_connect.cc:1410
      #20 0x000055757c723bba in handle_one_connection (arg=0x55757f181068) at /data/src/10.5/sql/sql_connect.cc:1312
      #21 0x000055757cc8248f in pfs_spawn_thread (arg=0x55757f167248) at /data/src/10.5/storage/perfschema/pfs.cc:2201
      #22 0x00007fa2c3dbe609 in start_thread (arg=<optimized out>) at pthread_create.c:477
      #23 0x00007fa2c3992293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
      

      Reproducible on 10.5, 10.6.
      A non-debug build doesn't crash on my machine, but a non-debug ASAN build does (also with SIGSEGV), so it is not just a debug problem.

      Couldn't reproduce on 10.2-10.4.

      Attachments

        Activity

          bertrandop here is the fix https://github.com/an3l/server/commit/086b9167bcbea369bf2bae0843e0085123701d29
          based on commit https://github.com/MariaDB/server/commit/043a3a0176e2#diff-f223b918b8e982bb3edaed26dc567ac653c0cf35f5ca624e2e3b664d4be5d49dR10333 which introduced it.
          Example of the test with the fix:

          worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 16000..16019
          INSTALL SONAME 'ha_connect';
          CREATE TABLE t (f INT) ENGINE=CONNECT;
          Warnings:
          Warning	1105	No table_type. Will be set to DOS
          Warning	1105	No file name. Table will use t.dos
          show create table t;
          Table	Create Table
          t	CREATE TABLE `t` (
            `f` int(11) DEFAULT NULL
          ) ENGINE=CONNECT DEFAULT CHARSET=latin1
          ALTER TABLE t ENGINE InnoDB;
          show create table t;
          Table	Create Table
          t	CREATE TABLE `t` (
            `f` int(11) DEFAULT NULL
          ) ENGINE=InnoDB DEFAULT CHARSET=latin1
          DROP TABLE t;
          CREATE TABLE t (f INT) ENGINE=CONNECT;
          Warnings:
          Warning	1105	No table_type. Will be set to DOS
          Warning	1105	No file name. Table will use t.dos
          Warning	1105	Default file /dev/shm/var_auto_p2EI/mysqld.1/data/./test/t.dos already exists
          show create table t;
          Table	Create Table
          t	CREATE TABLE `t` (
            `f` int(11) DEFAULT NULL
          ) ENGINE=CONNECT DEFAULT CHARSET=latin1
          ALTER TABLE t ENGINE Aria;
          show create table t;
          Table	Create Table
          t	CREATE TABLE `t` (
            `f` int(11) DEFAULT NULL
          ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
          DROP TABLE t;
          CREATE TABLE t (f INT) ENGINE=CONNECT;
          Warnings:
          Warning	1105	No table_type. Will be set to DOS
          Warning	1105	No file name. Table will use t.dos
          Warning	1105	Default file /dev/shm/var_auto_p2EI/mysqld.1/data/./test/t.dos already exists
          show create table t;
          Table	Create Table
          t	CREATE TABLE `t` (
            `f` int(11) DEFAULT NULL
          ) ENGINE=CONNECT DEFAULT CHARSET=latin1
          ALTER TABLE t ENGINE MYISAM;
          show create table t;
          Table	Create Table
          t	CREATE TABLE `t` (
            `f` int(11) DEFAULT NULL
          ) ENGINE=MyISAM DEFAULT CHARSET=latin1
          DROP TABLE t;
          UNINSTALL SONAME 'ha_connect';
          main.anel 'innodb'                       [ pass ]     16
          --------------------------------------------------------------------------
          The servers were restarted 0 times
          Spent 0.016 of 1 seconds executing testcases
           
          Completed: All 1 tests were successful.
          

          However there are failing tests in other suite with this fix.

          Failing test(s): main.log_tables main.mysqldump main.mysql_upgrade main.statistics main.partition_cache_innodb main.mysql_upgrade_view main.column_compression main.merge main.type_bit_innodb main.type_temporal_innodb
          

          Will assign monty to review and suggest how to proceed for 10.5.
          Alternative could be to disable initialization of table_options in innobase (https://github.com/MariaDB/server/blob/10.5/storage/innobase/handler/ha_innodb.cc#L3847)([~serg] )? but with that there are other types of errors.

          anel Anel Husakovic added a comment - bertrandop here is the fix https://github.com/an3l/server/commit/086b9167bcbea369bf2bae0843e0085123701d29 based on commit https://github.com/MariaDB/server/commit/043a3a0176e2#diff-f223b918b8e982bb3edaed26dc567ac653c0cf35f5ca624e2e3b664d4be5d49dR10333 which introduced it. Example of the test with the fix: worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 16000..16019 INSTALL SONAME 'ha_connect'; CREATE TABLE t (f INT) ENGINE=CONNECT; Warnings: Warning 1105 No table_type. Will be set to DOS Warning 1105 No file name. Table will use t.dos show create table t; Table Create Table t CREATE TABLE `t` ( `f` int(11) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 ALTER TABLE t ENGINE InnoDB; show create table t; Table Create Table t CREATE TABLE `t` ( `f` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t; CREATE TABLE t (f INT) ENGINE=CONNECT; Warnings: Warning 1105 No table_type. Will be set to DOS Warning 1105 No file name. Table will use t.dos Warning 1105 Default file /dev/shm/var_auto_p2EI/mysqld.1/data/./test/t.dos already exists show create table t; Table Create Table t CREATE TABLE `t` ( `f` int(11) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 ALTER TABLE t ENGINE Aria; show create table t; Table Create Table t CREATE TABLE `t` ( `f` int(11) DEFAULT NULL ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 DROP TABLE t; CREATE TABLE t (f INT) ENGINE=CONNECT; Warnings: Warning 1105 No table_type. Will be set to DOS Warning 1105 No file name. Table will use t.dos Warning 1105 Default file /dev/shm/var_auto_p2EI/mysqld.1/data/./test/t.dos already exists show create table t; Table Create Table t CREATE TABLE `t` ( `f` int(11) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 ALTER TABLE t ENGINE MYISAM; show create table t; Table Create Table t CREATE TABLE `t` ( `f` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t; UNINSTALL SONAME 'ha_connect'; main.anel 'innodb' [ pass ] 16 -------------------------------------------------------------------------- The servers were restarted 0 times Spent 0.016 of 1 seconds executing testcases   Completed: All 1 tests were successful. However there are failing tests in other suite with this fix. Failing test(s): main.log_tables main.mysqldump main.mysql_upgrade main.statistics main.partition_cache_innodb main.mysql_upgrade_view main.column_compression main.merge main.type_bit_innodb main.type_temporal_innodb Will assign monty to review and suggest how to proceed for 10.5 . Alternative could be to disable initialization of table_options in innobase ( https://github.com/MariaDB/server/blob/10.5/storage/innobase/handler/ha_innodb.cc#L3847)([~serg ] )? but with that there are other types of errors.
          monty Michael Widenius added a comment - - edited

          o Answer Anel's question about two calls to quick_rm_table:

          When doing an alter table from one engine to another, we need two
          calls to quick_rm_table().

          • First is to delete just the .frm file of the #sql-backup table. This contains
            a backup of the original table definition.
          • The second call is to delete the original table from the OLD engine.

          The difference compared to before and after "commit 043a3a0176" is
          that if the engine ios changed in alter table, we don't create
          a #sql-backup in the new engine but instead create directly the
          final name.

          For example, assume you do for an myisam table

          alter table t1 engine=aria;

          The files during alter table in the new code are:

          t1.MAI
          t1.MAD
          t1.frm
          t1.MYD
          t1.MYI
          #sql-backup-4b21-3.frm

          In the old code we would had:
          t1.frm
          t1.MYD
          t1.MYI
          #sql-backup-4b21-3.frm
          #sql-backup-4b21-3.MAI
          #sql-backup-4b21-3.MAD

          The new code avoids an extra rename (or move) of #sql-backup-4b21-3.MAI
          and #sql-backup-4b21-3.MAD to t1.MAI and t1.MAD.

          The problem with connect is that I had not anticipated that the engine would internally, as part of drop table, try to open
          the original .frm file.

          The fix is to ensure that we are using the old method with connect engine.
          This could probably be achieved by adding HA_REUSES_FILE_NAMES as ha_table_flag for connect.

          Inital testing suggests that this works. Now running a full test before pushing

          monty Michael Widenius added a comment - - edited o Answer Anel's question about two calls to quick_rm_table: When doing an alter table from one engine to another, we need two calls to quick_rm_table(). First is to delete just the .frm file of the #sql-backup table. This contains a backup of the original table definition. The second call is to delete the original table from the OLD engine. The difference compared to before and after "commit 043a3a0176" is that if the engine ios changed in alter table, we don't create a #sql-backup in the new engine but instead create directly the final name. For example, assume you do for an myisam table alter table t1 engine=aria; The files during alter table in the new code are: t1.MAI t1.MAD t1.frm t1.MYD t1.MYI #sql-backup-4b21-3.frm In the old code we would had: t1.frm t1.MYD t1.MYI #sql-backup-4b21-3.frm #sql-backup-4b21-3.MAI #sql-backup-4b21-3.MAD The new code avoids an extra rename (or move) of #sql-backup-4b21-3.MAI and #sql-backup-4b21-3.MAD to t1.MAI and t1.MAD. The problem with connect is that I had not anticipated that the engine would internally, as part of drop table, try to open the original .frm file. The fix is to ensure that we are using the old method with connect engine. This could probably be achieved by adding HA_REUSES_FILE_NAMES as ha_table_flag for connect. Inital testing suggests that this works. Now running a full test before pushing

          The problem with connect is that I had not anticipated that the engine would internally, as part of drop table, try to open the original .frm file
          Most Connect tables don't need to do anything in that context. Only "inward" tables (the ones for which the data file were not specified at creation and has been by default made in the current database) must erase that file. To do this, they don't need to really "open" the frm but just to know what is the name of the file to delete. For this they need the Option structure retrieved from the share structure.
          The above bug is that when retrieving the pointer to the Option from the share structure, an invalid pointer is returned by version 10.5 (only?) causing the crash when used.

          bertrandop Olivier Bertrand added a comment - The problem with connect is that I had not anticipated that the engine would internally, as part of drop table, try to open the original .frm file Most Connect tables don't need to do anything in that context. Only "inward" tables (the ones for which the data file were not specified at creation and has been by default made in the current database) must erase that file. To do this, they don't need to really "open" the frm but just to know what is the name of the file to delete. For this they need the Option structure retrieved from the share structure. The above bug is that when retrieving the pointer to the Option from the share structure, an invalid pointer is returned by version 10.5 (only?) causing the crash when used.

          Pushed to 10.5

          monty Michael Widenius added a comment - Pushed to 10.5
          anel Anel Husakovic added a comment - Pushed with the patch https://github.com/MariaDB/server/commit/1799caa3a1305d21acaa37169e6b14307b4b5f08 thanks monty

          People

            monty Michael Widenius
            elenst Elena Stepanova
            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.