Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cached RocksDB transaction object accessed after delete by XA COMMIT #1406

Open
laurynas-biveinis opened this issue Dec 12, 2023 · 0 comments

Comments

@laurynas-biveinis
Copy link
Contributor

In 8.0.32 but not 8.0.28, the following test, reduced from main.mdl_sync test, which does not fail:

--source include/count_sessions.inc

--echo #
--echo # Bug#21021848 ASSERTION `M_STATUS == DA_ERROR' FAILED.
--echo #
CREATE TABLE t1(c1 INT NOT NULL) ENGINE=CSV;
CREATE TABLE t2(c1 INT NOT NULL) ENGINE=InnoDB;

--echo # Emulate corruption of t1
LOCK TABLES t1 WRITE;
INSERT INTO t1 VALUES(0);
CHECK TABLE t1;
UNLOCK TABLES;

--echo # Start XA txn on default
XA START 'test2';
--echo # Acquire SR on t2
SELECT * FROM t2;
--echo # Block IS query just before calling lock_table_names() (before X on t1)
SET DEBUG_SYNC='recover_ot_repair SIGNAL parked WAIT_FOR go';
--send select table_name, table_type, auto_increment, table_comment from information_schema.tables where table_schema='test' and table_name='t1';

--echo # Create a new conncection which will compete for MDL lock
--connect (con1,localhost,root,,)
--echo # Wait until default becomes blocked
SET DEBUG_SYNC='now WAIT_FOR parked';
--echo # Try to acquire X on t1 and t2, which will block while default
--echo # holds SR on t2
--send DROP TABLES t1, t2

--echo # Create control connection
--connect (con2,localhost,root,,)

--echo # Wait until con1 is blocked
let $wait_condition=
  select count(*) = 1 from information_schema.processlist
  where state = "Waiting for table metadata lock" and
        info = "DROP TABLES t1, t2";
--source include/wait_condition.inc
--echo # Wake up XA txn/IS query on default
SET DEBUG_SYNC='now SIGNAL go';
--echo # Disconnect control connection
--disconnect con2
--source include/wait_until_disconnected.inc

--echo # Switch to default connection
--connection default
--echo # Wait for IS query which will try repair t1 which requires X.
--echo # Previously that resulted in deadlock with con1 over t1,
--echo # but now t1 is skipped and a warning is issued
--reap

--echo # Finish XA txn 'test2' to release SR on t2 so that con1
--echo # becomes unblocked
XA END 'test2';
XA PREPARE 'test2';
XA COMMIT 'test2';

--echo # Cleanup
SET DEBUG_SYNC= 'RESET';

--echo # Clean up con1 now that the XA txn has finished
--connection con1
--echo # Wait for the now unblocked DROP t1, t2 to complete
--reap
--echo # Disconnecting con1
--disconnect con1
--source include/wait_until_disconnected.inc

--echo # Switching to back to default at end of test case
--connection default

--echo #
--echo # Bug#26739438 DEADLOCK ON GET_LOCK(..., 0)
--echo #
--echo # Run GET_LOCK(...,0) from two connections to which would previously
--echo # cause deadlock

CREATE TABLE t1(i INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0), (1);

--echo # Starting con0
connect (con0,localhost,root,,test,,);
SELECT i FROM t1 WHERE i = 0 AND GET_LOCK(i, 0);

--echo # Starting con1
connect (con1,localhost,root,,test,,);
SELECT i FROM t1 WHERE i = 1 AND GET_LOCK(i, 0);

--echo # Send query which will do a 0-wait on i=0 while holding lock on i=1
SET DEBUG_SYNC='mdl_acquire_lock_wait SIGNAL wait0 WAIT_FOR go0';
--send SELECT i FROM t1 WHERE GET_LOCK(i, 0) AND i = 0

--echo # Switch to con0. Send query which will do a 0-wait on i=1 while
--echo # holding lock on i=0
connection con0;
SET DEBUG_SYNC='mdl_acquire_lock_wait SIGNAL wait1 WAIT_FOR go1';
--send SELECT i FROM t1 WHERE GET_LOCK(i, 0) AND i = 1

--echo # Switch to default connection and wait until both con0 and con1
--echo # are ready to check for deadlocks 
connection default;
SET DEBUG_SYNC='now WAIT_FOR wait0';
SET DEBUG_SYNC='now WAIT_FOR wait1';

--echo # Tell both connections to proceed
SET DEBUG_SYNC='now SIGNAL go0';
SET DEBUG_SYNC='now SIGNAL go1';

--echo # Wait for con0
connection con0;
--reap

--echo # Wait for con1 (should not deadlock)
connection con1;
--reap

connection default;
disconnect con0;
disconnect con1;

DROP TABLE t1;

# Check that all connections opened by test cases in this file are really
# gone so execution of other tests won't be affected by their presence.
--source include/wait_until_count_sessions.inc

Results in

=================================================================
==30785==ERROR: AddressSanitizer: heap-use-after-free on address 0x00013ce42680 at pc 0x000105793474 bp 0x00017aed1040 sp 0x00017aed1038
READ of size 8 at 0x00013ce42680 thread T83
    #0 0x105793470 in myrocks::Rdb_transaction_impl::set_lock_timeout(int, myrocks::TABLE_TYPE) ha_rocksdb.cc:4830
    #1 0x1056eecc0 in myrocks::get_or_create_tx(THD*, myrocks::TABLE_TYPE) ha_rocksdb.cc:5870
    #2 0x105720d74 in myrocks::ha_rocksdb::external_lock(THD*, int) ha_rocksdb.cc:14032
    #3 0x10078d608 in handler::ha_external_lock(THD*, int) handler.cc:8244
    #4 0x100f939b8 in lock_external(THD*, TABLE**, unsigned int) lock.cc:402
    #5 0x100f91350 in mysql_lock_tables(THD*, TABLE**, unsigned long, unsigned int) lock.cc:338
    #6 0x10152e32c in lock_dictionary_tables(THD*, Table_ref*, unsigned int, unsigned int) sql_base.cc:7279
    #7 0x103e23450 in dd::Open_dictionary_tables_ctx::open_tables() transaction_impl.cc:123
    #8 0x104208cac in bool dd::cache::Storage_adapter::store<dd::Table>(THD*, dd::Table*) storage_adapter.cc:334
    #9 0x103eb91c4 in bool dd::cache::Dictionary_client::store<dd::Table>(dd::Table*) dictionary_client.cc:2565
    #10 0x101acbfa8 in rea_create_base_table(THD*, char const*, dd::Schema const&, char const*, char const*, HA_CREATE_INFO*, List<Create_field>&, unsigned int, KEY*, Alter_info::enum_enable_or_disable, unsigned int, FOREIGN_KEY*, Mem_root_array<Sql_check_constraint_spec*> const*, handler*, bool, bool, partition_info*, bool*, std::__1::unique_ptr<dd::Table, std::__1::default_delete<dd::Table>>*, handlerton**) sql_table.cc:1112
    #11 0x101a513cc in create_table_impl(THD*, dd::Schema const&, char const*, char const*, char const*, char const*, HA_CREATE_INFO*, Alter_info*, bool, unsigned int, bool, bool, bool, bool*, KEY**, unsigned int*, Alter_info::enum_enable_or_disable, FOREIGN_KEY**, unsigned int*, FOREIGN_KEY*, unsigned int, dd::Table const*, unsigned int, bool, std::__1::unique_ptr<dd::Table, std::__1::default_delete<dd::Table>>*, handlerton**) sql_table.cc:8983
    #12 0x101a4e7dc in mysql_create_table_no_lock(THD*, char const*, char const*, HA_CREATE_INFO*, Alter_info*, unsigned int, bool, bool*, handlerton**) sql_table.cc:9224
    #13 0x101a57ea4 in mysql_create_table(THD*, Table_ref*, HA_CREATE_INFO*, Alter_info*) sql_table.cc:10141
    #14 0x1016079e4 in Sql_cmd_create_table::execute(THD*) sql_cmd_ddl_table.cc:434
    #15 0x10180a328 in mysql_execute_command(THD*, bool, unsigned long long*) sql_parse.cc:4424
    #16 0x101801bd0 in dispatch_sql_command(THD*, Parser_state*, unsigned long long*) sql_parse.cc:6263
    #17 0x1017f75d4 in dispatch_command(THD*, COM_DATA const*, enum_server_command) sql_parse.cc:2544
    #18 0x1017fd0a8 in do_command(THD*) sql_parse.cc:1724
    #19 0x101e65d60 in handle_connection(void*) connection_handler_per_thread.cc:307
    #20 0x106642a18 in pfs_spawn_thread(void*) pfs.cc:3022
    #21 0x190465030 in _pthread_start+0x84 (libsystem_pthread.dylib:arm64e+0x7030)
    #22 0x19045fe38 in thread_start+0x4 (libsystem_pthread.dylib:arm64e+0x1e38)

0x00013ce42680 is located 0 bytes inside of 616-byte region [0x00013ce42680,0x00013ce428e8)
freed by thread T83 here:
    #0 0x120fad52c in wrap__ZdlPv+0x74 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x6152c)
    #1 0x10582c9a0 in myrocks::rocksdb_commit_by_xid(handlerton*, xid_t*) ha_rocksdb.cc:6094
    #2 0x101cbeb00 in (anonymous namespace)::commit_one_ht(THD*, st_plugin_int**, void*) tc_log.cc:189
    #3 0x10189b13c in plugin_foreach_with_mask(THD*, bool (**)(THD*, st_plugin_int**, void*), int, unsigned int, void*) sql_plugin.cc:2843
    #4 0x10189ba8c in plugin_foreach_with_mask(THD*, bool (*)(THD*, st_plugin_int**, void*), int, unsigned int, void*) sql_plugin.cc:2856
    #5 0x101cbe424 in trx_coordinator::commit_detached_by_xid(THD*, bool) tc_log.cc:115
    #6 0x101cbf4c4 in trx_coordinator::commit_in_engines(THD*, bool, bool) tc_log.cc:144
    #7 0x1036e456c in MYSQL_BIN_LOG::commit(THD*, bool) binlog.cc:10781
    #8 0x101d27728 in Sql_cmd_xa_commit::process_detached_xa_commit(THD*) sql_xa_commit.cc:211
    #9 0x101d27254 in Sql_cmd_xa_commit::trans_xa_commit(THD*) sql_xa_commit.cc:94
    #10 0x101d26fc4 in Sql_cmd_xa_commit::execute(THD*) sql_xa_commit.cc:64
    #11 0x10180a1a0 in mysql_execute_command(THD*, bool, unsigned long long*) sql_parse.cc:5489
    #12 0x101801bd0 in dispatch_sql_command(THD*, Parser_state*, unsigned long long*) sql_parse.cc:6263
    #13 0x1017f75d4 in dispatch_command(THD*, COM_DATA const*, enum_server_command) sql_parse.cc:2544
    #14 0x1017fd0a8 in do_command(THD*) sql_parse.cc:1724
    #15 0x101e65d60 in handle_connection(void*) connection_handler_per_thread.cc:307
    #16 0x106642a18 in pfs_spawn_thread(void*) pfs.cc:3022
    #17 0x190465030 in _pthread_start+0x84 (libsystem_pthread.dylib:arm64e+0x7030)
    #18 0x19045fe38 in thread_start+0x4 (libsystem_pthread.dylib:arm64e+0x1e38)

previously allocated by thread T83 here:
    #0 0x120fad0ec in wrap__Znwm+0x74 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x610ec)
    #1 0x1081a934c in rocksdb::WriteCommittedTxnDB::BeginTransaction(rocksdb::WriteOptions const&, rocksdb::TransactionOptions const&, rocksdb::Transaction*) pessimistic_transaction_db.cc:185
    #2 0x105797390 in myrocks::Rdb_transaction_impl::start_tx(myrocks::TABLE_TYPE) ha_rocksdb.cc:5255
    #3 0x1056eee4c in myrocks::get_or_create_tx(THD*, myrocks::TABLE_TYPE) ha_rocksdb.cc:5864
    #4 0x105720d74 in myrocks::ha_rocksdb::external_lock(THD*, int) ha_rocksdb.cc:14032
    #5 0x10078d608 in handler::ha_external_lock(THD*, int) handler.cc:8244
    #6 0x100f939b8 in lock_external(THD*, TABLE**, unsigned int) lock.cc:402
    #7 0x100f91350 in mysql_lock_tables(THD*, TABLE**, unsigned long, unsigned int) lock.cc:338
    #8 0x10152e32c in lock_dictionary_tables(THD*, Table_ref*, unsigned int, unsigned int) sql_base.cc:7279
    #9 0x103e23450 in dd::Open_dictionary_tables_ctx::open_tables() transaction_impl.cc:123
    #10 0x104208cac in bool dd::cache::Storage_adapter::store<dd::Table>(THD*, dd::Table*) storage_adapter.cc:334
    #11 0x103eb91c4 in bool dd::cache::Dictionary_client::store<dd::Table>(dd::Table*) dictionary_client.cc:2565
    #12 0x101acbfa8 in rea_create_base_table(THD*, char const*, dd::Schema const&, char const*, char const*, HA_CREATE_INFO*, List<Create_field>&, unsigned int, KEY*, Alter_info::enum_enable_or_disable, unsigned int, FOREIGN_KEY*, Mem_root_array<Sql_check_constraint_spec*> const*, handler*, bool, bool, partition_info*, bool*, std::__1::unique_ptr<dd::Table, std::__1::default_delete<dd::Table>>*, handlerton**) sql_table.cc:1112
    #13 0x101a513cc in create_table_impl(THD*, dd::Schema const&, char const*, char const*, char const*, char const*, HA_CREATE_INFO*, Alter_info*, bool, unsigned int, bool, bool, bool, bool*, KEY**, unsigned int*, Alter_info::enum_enable_or_disable, FOREIGN_KEY**, unsigned int*, FOREIGN_KEY*, unsigned int, dd::Table const*, unsigned int, bool, std::__1::unique_ptr<dd::Table, std::__1::default_delete<dd::Table>>*, handlerton**) sql_table.cc:8983
    #14 0x101a4e7dc in mysql_create_table_no_lock(THD*, char const*, char const*, HA_CREATE_INFO*, Alter_info*, unsigned int, bool, bool*, handlerton**) sql_table.cc:9224
    #15 0x101a57ea4 in mysql_create_table(THD*, Table_ref*, HA_CREATE_INFO*, Alter_info*) sql_table.cc:10141
    #16 0x1016079e4 in Sql_cmd_create_table::execute(THD*) sql_cmd_ddl_table.cc:434
    #17 0x10180a328 in mysql_execute_command(THD*, bool, unsigned long long*) sql_parse.cc:4424
    #18 0x101801bd0 in dispatch_sql_command(THD*, Parser_state*, unsigned long long*) sql_parse.cc:6263
    #19 0x1017f75d4 in dispatch_command(THD*, COM_DATA const*, enum_server_command) sql_parse.cc:2544
    #20 0x1017fd0a8 in do_command(THD*) sql_parse.cc:1724
    #21 0x101e65d60 in handle_connection(void*) connection_handler_per_thread.cc:307
    #22 0x106642a18 in pfs_spawn_thread(void*) pfs.cc:3022
    #23 0x190465030 in _pthread_start+0x84 (libsystem_pthread.dylib:arm64e+0x7030)
    #24 0x19045fe38 in thread_start+0x4 (libsystem_pthread.dylib:arm64e+0x1e38)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant