MW-384 protect access to wsrep_ready variable with mutex

This commit is contained in:
Alexey Yurchenko 2017-06-19 17:23:02 +07:00 committed by Jan Lindström
parent 8da6b4ef52
commit 86d31ce9f1
8 changed files with 33 additions and 23 deletions

View file

@ -1,7 +1,7 @@
#!/usr/bin/perl #!/usr/bin/perl
# -*- cperl -*- # -*- cperl -*-
# #
# Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -53,7 +53,7 @@ my $cwd = cwd();
my $basedir; my $basedir;
my $socket = '/tmp/mysql.sock'; my $socket = '/tmp/mysql.sock';
my $version = '5.5.38'; my $version = '5.5.58';
sub which sub which
{ {
@ -204,7 +204,7 @@ $flags->{embedded_libs} =
[@ldflags,@lib_e_opts,'','','','','']; [@ldflags,@lib_e_opts,'','','','',''];
$flags->{include} = ["-I$pkgincludedir"]; $flags->{include} = ["-I$pkgincludedir"];
$flags->{cflags} = [@{$flags->{include}},split(" ",'-Wall -DWITH_WSREP -DWSREP_PROC_INFO -DMYSQL_MAX_VARIABLE_VALUE_LEN=2048 -DWITH_INNODB_DISALLOW_WRITES -O2 -g -DNDEBUG -DDBUG_OFF')]; $flags->{cflags} = [@{$flags->{include}},split(" ",'')];
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# Remove some options that a client doesn't have to care about # Remove some options that a client doesn't have to care about

View file

@ -7929,7 +7929,7 @@ SHOW_VAR status_vars[]= {
#endif #endif
#ifdef WITH_WSREP #ifdef WITH_WSREP
{"wsrep_connected", (char*) &wsrep_connected, SHOW_BOOL}, {"wsrep_connected", (char*) &wsrep_connected, SHOW_BOOL},
{"wsrep_ready", (char*) &wsrep_ready, SHOW_BOOL}, {"wsrep_ready", (char*) &wsrep_show_ready, SHOW_FUNC},
{"wsrep_cluster_state_uuid", (char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR}, {"wsrep_cluster_state_uuid", (char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR},
{"wsrep_cluster_conf_id", (char*) &wsrep_cluster_conf_id, SHOW_LONGLONG}, {"wsrep_cluster_conf_id", (char*) &wsrep_cluster_conf_id, SHOW_LONGLONG},
{"wsrep_cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR}, {"wsrep_cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR},

View file

@ -3794,7 +3794,7 @@ err_during_init:
*/ */
if (wsrep_node_dropped && wsrep_restart_slave) if (wsrep_node_dropped && wsrep_restart_slave)
{ {
if (wsrep_ready) if (wsrep_ready_get())
{ {
WSREP_INFO("Slave error due to node temporarily non-primary" WSREP_INFO("Slave error due to node temporarily non-primary"
"SQL slave will continue"); "SQL slave will continue");

View file

@ -851,7 +851,7 @@ bool do_command(THD *thd)
* bail out if DB snapshot has not been installed. We however, * bail out if DB snapshot has not been installed. We however,
* allow queries "SET" and "SHOW", they are trapped later in execute_command * allow queries "SET" and "SHOW", they are trapped later in execute_command
*/ */
if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready_get() &&
command != COM_QUERY && command != COM_QUERY &&
command != COM_PING && command != COM_PING &&
command != COM_QUIT && command != COM_QUIT &&
@ -2382,7 +2382,7 @@ mysql_execute_command(THD *thd)
We additionally allow all other commands that do not change data in We additionally allow all other commands that do not change data in
case wsrep_dirty_reads is enabled. case wsrep_dirty_reads is enabled.
*/ */
if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready_get() &&
lex->sql_command != SQLCOM_SET_OPTION && lex->sql_command != SQLCOM_SET_OPTION &&
!(thd->variables.wsrep_dirty_reads && !(thd->variables.wsrep_dirty_reads &&
!is_update_query(lex->sql_command)) && !is_update_query(lex->sql_command)) &&

View file

@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <sql_plugin.h> // SHOW_MY_BOOL
#include <mysqld.h> #include <mysqld.h>
#include <sql_class.h> #include <sql_class.h>
#include <sql_parse.h> #include <sql_parse.h>
@ -295,7 +296,7 @@ wsrep_view_handler_cb (void* app_ctx,
// version change // version change
if (view->proto_ver != wsrep_protocol_version) if (view->proto_ver != wsrep_protocol_version)
{ {
my_bool wsrep_ready_saved= wsrep_ready; my_bool wsrep_ready_saved= wsrep_ready_get();
wsrep_ready_set(FALSE); wsrep_ready_set(FALSE);
WSREP_INFO("closing client connections for " WSREP_INFO("closing client connections for "
"protocol change %ld -> %d", "protocol change %ld -> %d",
@ -409,16 +410,34 @@ out:
return WSREP_CB_SUCCESS; return WSREP_CB_SUCCESS;
} }
void wsrep_ready_set (my_bool x) my_bool wsrep_ready_set (my_bool x)
{ {
WSREP_DEBUG("Setting wsrep_ready to %d", x); WSREP_DEBUG("Setting wsrep_ready to %d", x);
if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
if (wsrep_ready != x) my_bool ret= (wsrep_ready != x);
if (ret)
{ {
wsrep_ready= x; wsrep_ready= x;
mysql_cond_signal (&COND_wsrep_ready); mysql_cond_signal (&COND_wsrep_ready);
} }
mysql_mutex_unlock (&LOCK_wsrep_ready); mysql_mutex_unlock (&LOCK_wsrep_ready);
return ret;
}
my_bool wsrep_ready_get (void)
{
if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
my_bool ret= wsrep_ready;
mysql_mutex_unlock (&LOCK_wsrep_ready);
return ret;
}
int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff)
{
var->type= SHOW_MY_BOOL;
var->value= buff;
*((my_bool *)buff)= wsrep_ready_get();
return 0;
} }
// Wait until wsrep has reached ready state // Wait until wsrep has reached ready state
@ -437,17 +456,8 @@ void wsrep_ready_wait ()
static void wsrep_synced_cb(void* app_ctx) static void wsrep_synced_cb(void* app_ctx)
{ {
WSREP_INFO("Synchronized with group, ready for connections"); WSREP_INFO("Synchronized with group, ready for connections");
bool signal_main= false; my_bool signal_main= wsrep_ready_set(TRUE);
if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
if (!wsrep_ready)
{
wsrep_ready= TRUE;
mysql_cond_signal (&COND_wsrep_ready);
signal_main= true;
}
local_status.set(WSREP_MEMBER_SYNCED); local_status.set(WSREP_MEMBER_SYNCED);
mysql_mutex_unlock (&LOCK_wsrep_ready);
if (signal_main) if (signal_main)
{ {

View file

@ -115,7 +115,6 @@ enum enum_wsrep_sync_wait {
// MySQL status variables // MySQL status variables
extern my_bool wsrep_connected; extern my_bool wsrep_connected;
extern my_bool wsrep_ready;
extern const char* wsrep_cluster_state_uuid; extern const char* wsrep_cluster_state_uuid;
extern long long wsrep_cluster_conf_id; extern long long wsrep_cluster_conf_id;
extern const char* wsrep_cluster_status; extern const char* wsrep_cluster_status;
@ -130,6 +129,7 @@ extern const char* wsrep_provider_vendor;
extern my_bool wsrep_inited; // whether wsrep is initialized ? extern my_bool wsrep_inited; // whether wsrep is initialized ?
int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff); int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff);
int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff);
void wsrep_free_status(THD *thd); void wsrep_free_status(THD *thd);
/* Filters out --wsrep-new-cluster oprtion from argv[] /* Filters out --wsrep-new-cluster oprtion from argv[]
@ -245,6 +245,7 @@ extern wsrep_seqno_t wsrep_locked_seqno;
#define WSREP_PROVIDER_EXISTS \ #define WSREP_PROVIDER_EXISTS \
(wsrep_provider && strncasecmp(wsrep_provider, WSREP_NONE, FN_REFLEN)) (wsrep_provider && strncasecmp(wsrep_provider, WSREP_NONE, FN_REFLEN))
extern my_bool wsrep_ready_get();
extern void wsrep_ready_wait(); extern void wsrep_ready_wait();
enum wsrep_trx_status { enum wsrep_trx_status {

View file

@ -26,7 +26,7 @@
#include <pthread.h> #include <pthread.h>
#include <cstdio> #include <cstdio>
void wsrep_ready_set (my_bool x); my_bool wsrep_ready_set (my_bool x);
ssize_t wsrep_sst_prepare (void** msg); ssize_t wsrep_sst_prepare (void** msg);
wsrep_cb_status wsrep_sst_donate_cb (void* app_ctx, wsrep_cb_status wsrep_sst_donate_cb (void* app_ctx,

View file

@ -1057,7 +1057,6 @@ wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx,
{ {
/* This will be reset when sync callback is called. /* This will be reset when sync callback is called.
* Should we set wsrep_ready to FALSE here too? */ * Should we set wsrep_ready to FALSE here too? */
// wsrep_notify_status(WSREP_MEMBER_DONOR);
local_status.set(WSREP_MEMBER_DONOR); local_status.set(WSREP_MEMBER_DONOR);
const char* method = (char*)msg; const char* method = (char*)msg;