Details
-
Bug
-
Status: Closed (View Workflow)
-
Critical
-
Resolution: Fixed
-
10.5, 10.6, 10.11, 10.4(EOL), 10.7(EOL), 10.8(EOL), 10.10(EOL)
-
None
Description
trx->mysql_thd can be zeroed-out between thd_get_thread_id() and thd_query_safe() calls in fill_trx_row(). trx_disconnect_prepared() zeroes out trx->mysql_thd. And this can cause null pointer dereferencing in fill_trx_row().
The bug can be reproduced with the following new sync point:
diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc
|
index 2dc39118d3d..c2cc8c970b0 100644 |
--- a/storage/innobase/trx/trx0i_s.cc
|
+++ b/storage/innobase/trx/trx0i_s.cc
|
@@ -461,6 +461,8 @@ fill_trx_row( |
row->trx_mysql_thread_id = thd_get_thread_id(trx->mysql_thd);
|
|
char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1]; |
+ ut_d(if (trx->state == TRX_STATE_PREPARED) |
+ DEBUG_SYNC_C("fill_trx_row_before_query_request")); |
if (size_t stmt_len = thd_query_safe(trx->mysql_thd, query, |
sizeof query)) {
|
row->trx_query = static_cast<const char*>( |
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
|
index 3b19d213d5a..92bf9de375a 100644 |
--- a/storage/innobase/trx/trx0trx.cc
|
+++ b/storage/innobase/trx/trx0trx.cc
|
@@ -550,6 +550,7 @@ void trx_disconnect_prepared(trx_t *trx) |
trx->read_view.close();
|
trx->is_recovered= true; |
trx->mysql_thd= NULL;
|
+ DEBUG_SYNC_C("trx_disconnect_prepared_reset_thd"); |
/* todo/fixme: suggest to do it at innodb prepare */ |
trx->will_lock= false; |
trx_sys.rw_trx_hash.put_pins(trx);
|
and the following test case:
--source include/have_innodb.inc
|
--source include/have_debug.inc
|
--source include/have_debug_sync.inc
|
--source include/count_sessions.inc
|
|
--connection default |
create table t (a int) engine=innodb; |
insert into t values(1); |
|
--connect (con_xa, localhost, root,,)
|
SET DEBUG_SYNC="trx_disconnect_prepared_reset_thd SIGNAL thd_reset"; |
xa start '1'; |
insert into t values(1); |
xa end '1'; |
xa prepare '1'; |
|
--connection default |
SET DEBUG_SYNC="fill_trx_row_before_query_request SIGNAL reached WAIT_FOR fill_row_cont"; |
--send select * from information_schema.innodb_trx;
|
|
--connect (con_sync, localhost, root,,)
|
SET DEBUG_SYNC="now WAIT_FOR reached"; |
--disconnect con_xa
|
SET DEBUG_SYNC="now WAIT_FOR thd_reset"; |
SET DEBUG_SYNC="now SIGNAL fill_row_cont"; |
--disconnect con_sync
|
|
--connection default |
--disable_result_log
|
# Must crash here with SIGSEGV if not fixed |
--reap;
|
--enable_result_log
|
xa commit '1'; |
drop table t;
|
SET DEBUG_SYNC="RESET"; |
--source include/wait_until_count_sessions.inc
|
It does not affect 10.3 as 10.3 does not detach XA on disconnection (compare THD::cleanup() in 10.3 and 10.4+ and see trans_xa_detach() in 10.4+ for details).
Until MDEV-29368 is fixed the workaround is not to use innodb_trx, innodb_locks and innodb_lock_waits from information_schema along with detached XA's.
Attachments
Issue Links
- blocks
-
MDEV-28709 unexpected X lock on Supremum in READ COMMITTED
- Closed
- is blocked by
-
MDEV-29368 Assertion `trx->mysql_thd == thd' failed in innobase_kill_query from process_timers/timer_handler and use-after-poison in innobase_kill_query
- Closed
- is caused by
-
MDEV-15773 Simplify away trx_sys_t::m_views
- Closed