Skip to content

Commit 148ebfb

Browse files
committed
Bug#36804874: The table access service from a non-THD thread
always frees the mysys thread When the calling thread does not have a THD attached (current_thd thread local is null) but it has mysys thread local set (THR_mysys is non-null) table_access_factory_v1::create() will assume that there's neither of the two and will call my_thread_init(). If the calling thread already has THR_mysys set, my_thread_init() is a no-op. However, table_access_factory_v1::destroy() does call my_thread_end() if there's no THD "parent" thread context to restore. This is never a no-op and as a result the calling thread looses its THR_mysys value. Thus, if further calls to THD methods (as e.g. done by the group_membership_listener::notify_view_change() calling THD::store_globals() that in turn calls set_my_thread_var_id()) that assume that THR_mysys is set are going to crash. Fixed by: 1. implementing a mysys API to check if THR_mysys is initialized: bool my_thread_is_inited() 2. Call this method in table_access_factory_v1::create() and cache the result in the Table_access structure. 3. At table_access_factory_v1::destroy(), call if the mysys THD was inited and only call my_thread_end() if it wasn't. No test case added as the sequence is used in an upcoming change and thus is going to be properly tested. Also removed a superfluous call to restore_globals(), as it's already called by THD::release_resources(). Change-Id: I5d1271cc62b6dc6f4eeab1aa7ec53d68f514d956
1 parent c6997b1 commit 148ebfb

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

include/my_thread.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,6 @@ extern void my_thread_global_end();
178178
// Need to be extern "C" for the time being, due to memcached.
179179
extern "C" bool my_thread_init();
180180
extern "C" void my_thread_end();
181+
extern bool my_thread_is_inited();
181182

182183
#endif /* MY_THREAD_INCLUDED */

mysys/my_thr_init.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,20 @@ extern "C" bool my_thread_init() {
293293
return false;
294294
}
295295

296+
bool my_thread_is_inited() {
297+
#ifndef NDEBUG
298+
return mysys_thread_var() != nullptr;
299+
#else
300+
/*
301+
Return true here because for non-debug binaries my_thread_end() should not
302+
be called on native threads because my_thread_init() is a no-op for these
303+
and my_thread_end() just deregisters the thread from P_S.
304+
And since there's no registration in P_S at my_thread_init() we should not
305+
be calling my_thread_end() for these threads.
306+
*/
307+
return true;
308+
#endif
309+
}
296310
/**
297311
Deallocate memory used by the thread for book-keeping
298312

sql/server_component/table_access_service.cc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,8 @@ class Table_access_impl {
528528
size_t m_max_count;
529529
bool m_write;
530530
bool m_in_tx;
531+
/** true if the mysys thread state needs cleanup */
532+
bool m_clear_mysys;
531533

532534
THD *m_parent_thd;
533535
THD *m_child_thd;
@@ -584,7 +586,11 @@ void TA_key_impl::key_copy(uchar *record, uint key_length) {
584586
}
585587

586588
Table_access_impl::Table_access_impl(THD *thd, size_t count)
587-
: m_current_count(0), m_max_count(count), m_write(false), m_in_tx(false) {
589+
: m_current_count(0),
590+
m_max_count(count),
591+
m_write(false),
592+
m_in_tx(false),
593+
m_clear_mysys{false} {
588594
m_parent_thd = thd;
589595

590596
m_child_thd = new THD(true);
@@ -597,6 +603,7 @@ Table_access_impl::Table_access_impl(THD *thd, size_t count)
597603
m_child_thd->security_context()->assign_user(
598604
STRING_WITH_LEN("table_access"));
599605
m_child_thd->security_context()->skip_grants("", "");
606+
this->m_clear_mysys = !my_thread_is_inited();
600607
my_thread_init();
601608
}
602609

@@ -635,7 +642,6 @@ Table_access_impl::~Table_access_impl() {
635642
}
636643

637644
m_child_thd->release_resources();
638-
m_child_thd->restore_globals();
639645

640646
if (m_parent_thd) m_parent_thd->store_globals();
641647

@@ -646,7 +652,7 @@ Table_access_impl::~Table_access_impl() {
646652
delete[] m_table_array;
647653
delete[] m_table_state_array;
648654

649-
if (!m_parent_thd) my_thread_end();
655+
if (m_clear_mysys && !m_parent_thd) my_thread_end();
650656

651657
// FIXME : kill flag ?
652658
// FIXME : nested THD status variables ?

0 commit comments

Comments
 (0)