Skip to content

Commit 59037d9

Browse files
author
Nirbhay Choubey
committed
MDEV-8208: Sporadic SEGFAULT on startup
Problem: When mysqld starts as a galera node, it creates 2 system threads (applier & rollbacker) using start_wsrep_THD(). These threads are created before plugin initialization (plugin_init()) for SST methods like rsync and xtrabackup. The threads' initialization itself can proceed in parallel to mysqld's main thread of execution. As a result, the thread initialization code (start_wsrep_THD()) can end up accessing some un/partially initialized structures (like maria_hton, in this particular case) resulting in segfault. Solution: Fixed by calling THD::init_for_queries() (which accesses maria_hton) only after the plugins have been initialized.
1 parent 30711c6 commit 59037d9

File tree

3 files changed

+56
-18
lines changed

3 files changed

+56
-18
lines changed

sql/mysqld.cc

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5125,11 +5125,6 @@ static int init_server_components()
51255125
{
51265126
set_ports(); // this is also called in network_init() later but we need
51275127
// to know mysqld_port now - lp:1071882
5128-
/*
5129-
Plugin initialization (plugin_init()) hasn't happened yet, set
5130-
maria_hton to 0.
5131-
*/
5132-
maria_hton= 0;
51335128
wsrep_init_startup(true);
51345129
}
51355130
}
@@ -5204,6 +5199,29 @@ static int init_server_components()
52045199
}
52055200
plugins_are_initialized= TRUE; /* Don't separate from init function */
52065201

5202+
#ifdef WITH_WSREP
5203+
/* Wait for wsrep threads to get created. */
5204+
if (wsrep_creating_startup_threads == 1) {
5205+
mysql_mutex_lock(&LOCK_thread_count);
5206+
while (wsrep_running_threads < 2)
5207+
{
5208+
mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
5209+
}
5210+
5211+
/* Now is the time to initialize threads for queries. */
5212+
THD *tmp;
5213+
I_List_iterator<THD> it(threads);
5214+
while ((tmp= it++))
5215+
{
5216+
if (tmp->wsrep_applier == true)
5217+
{
5218+
tmp->init_for_queries();
5219+
}
5220+
}
5221+
mysql_mutex_unlock(&LOCK_thread_count);
5222+
}
5223+
#endif
5224+
52075225
/* we do want to exit if there are any other unknown options */
52085226
if (remaining_argc > 1)
52095227
{
@@ -5412,7 +5430,6 @@ static void create_shutdown_thread()
54125430

54135431
#endif /* EMBEDDED_LIBRARY */
54145432

5415-
54165433
#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
54175434
static void handle_connections_methods()
54185435
{

sql/wsrep_mysqld.cc

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ my_bool wsrep_slave_UK_checks = 0; // slave thread does UK checks
9191
my_bool wsrep_slave_FK_checks = 0; // slave thread does FK checks
9292
bool wsrep_new_cluster = false; // Bootstrap the cluster ?
9393

94+
/*
95+
Set during the creation of first wsrep applier and rollback threads.
96+
Since these threads are critical, abort if the thread creation fails.
97+
*/
98+
my_bool wsrep_creating_startup_threads = 0;
99+
94100
// Use wsrep_gtid_domain_id for galera transactions?
95101
bool wsrep_gtid_mode = 0;
96102
// gtid_domain_id for galera transactions.
@@ -792,6 +798,7 @@ void wsrep_init_startup (bool first)
792798

793799
if (!wsrep_start_replication()) unireg_abort(1);
794800

801+
wsrep_creating_startup_threads= 1;
795802
wsrep_create_rollbacker();
796803
wsrep_create_appliers(1);
797804

@@ -1719,16 +1726,11 @@ pthread_handler_t start_wsrep_THD(void *arg)
17191726
THD *thd;
17201727
wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg;
17211728

1722-
if (my_thread_init())
1729+
if (my_thread_init() || (!(thd= new THD(true))))
17231730
{
1724-
WSREP_ERROR("Could not initialize thread");
1725-
return(NULL);
1731+
goto error;
17261732
}
17271733

1728-
if (!(thd= new THD(true)))
1729-
{
1730-
return(NULL);
1731-
}
17321734
mysql_mutex_lock(&LOCK_thread_count);
17331735
thd->thread_id=thread_id++;
17341736

@@ -1765,7 +1767,7 @@ pthread_handler_t start_wsrep_THD(void *arg)
17651767
statistic_increment(aborted_connects,&LOCK_status);
17661768
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
17671769

1768-
return(NULL);
1770+
goto error;
17691771
}
17701772

17711773
// </5.1.17>
@@ -1788,8 +1790,7 @@ pthread_handler_t start_wsrep_THD(void *arg)
17881790
statistic_increment(aborted_connects,&LOCK_status);
17891791
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
17901792
delete thd;
1791-
1792-
return(NULL);
1793+
goto error;
17931794
}
17941795

17951796
thd->system_thread= SYSTEM_THREAD_SLAVE_SQL;
@@ -1799,12 +1800,21 @@ pthread_handler_t start_wsrep_THD(void *arg)
17991800
//thd->version= refresh_version;
18001801
thd->proc_info= 0;
18011802
thd->set_command(COM_SLEEP);
1802-
thd->set_time();
1803-
thd->init_for_queries();
1803+
1804+
if (plugins_are_initialized)
1805+
{
1806+
thd->init_for_queries();
1807+
}
18041808

18051809
mysql_mutex_lock(&LOCK_thread_count);
18061810
wsrep_running_threads++;
18071811
mysql_cond_broadcast(&COND_thread_count);
1812+
1813+
if (wsrep_running_threads > 2)
1814+
{
1815+
wsrep_creating_startup_threads= 0;
1816+
}
1817+
18081818
mysql_mutex_unlock(&LOCK_thread_count);
18091819

18101820
processor(thd);
@@ -1842,6 +1852,15 @@ pthread_handler_t start_wsrep_THD(void *arg)
18421852
mysql_mutex_unlock(&LOCK_thread_count);
18431853
}
18441854
return(NULL);
1855+
1856+
error:
1857+
WSREP_ERROR("Failed to create/initialize system thread");
1858+
1859+
/* Abort if its the first applier/rollbacker thread. */
1860+
if (wsrep_creating_startup_threads < 2)
1861+
unireg_abort(1);
1862+
else
1863+
return NULL;
18451864
}
18461865

18471866

sql/wsrep_mysqld.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ extern my_bool wsrep_slave_FK_checks;
8686
extern my_bool wsrep_slave_UK_checks;
8787
extern ulong wsrep_running_threads;
8888
extern bool wsrep_new_cluster;
89+
extern my_bool wsrep_creating_startup_threads;
8990
extern bool wsrep_gtid_mode;
9091
extern uint32 wsrep_gtid_domain_id;
9192

@@ -341,6 +342,7 @@ int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
341342
#define wsrep_thr_init() do {} while(0)
342343
#define wsrep_thr_deinit() do {} while(0)
343344
#define wsrep_running_threads (0)
345+
#define wsrep_creating_startup_threads (0)
344346

345347
#endif /* WITH_WSREP */
346348
#endif /* WSREP_MYSQLD_H */

0 commit comments

Comments
 (0)