Fix deadlock in galeramon
The parameter extraction caused a recursive lock of the server spinlock. To work around this, an unlocked version of server_get_parameter is needed. Ideally, a lock-free setup would be used but due to this being a bug fix, it will have to be done later on.
This commit is contained in:
@ -358,6 +358,7 @@ extern void server_clear_status_nolock(SERVER *server, uint64_t bit);
|
|||||||
extern void server_transfer_status(SERVER *dest_server, const SERVER *source_server);
|
extern void server_transfer_status(SERVER *dest_server, const SERVER *source_server);
|
||||||
extern void server_add_mon_user(SERVER *server, const char *user, const char *passwd);
|
extern void server_add_mon_user(SERVER *server, const char *user, const char *passwd);
|
||||||
extern size_t server_get_parameter(const SERVER *server, const char *name, char* out, size_t size);
|
extern size_t server_get_parameter(const SERVER *server, const char *name, char* out, size_t size);
|
||||||
|
extern size_t server_get_parameter_nolock(const SERVER *server, const char *name, char* out, size_t size);
|
||||||
extern void server_update_credentials(SERVER *server, const char *user, const char *passwd);
|
extern void server_update_credentials(SERVER *server, const char *user, const char *passwd);
|
||||||
extern DCB* server_get_persistent(SERVER *server, const char *user, const char* ip, const char *protocol, int id);
|
extern DCB* server_get_persistent(SERVER *server, const char *user, const char* ip, const char *protocol, int id);
|
||||||
extern void server_update_address(SERVER *server, const char *address);
|
extern void server_update_address(SERVER *server, const char *address);
|
||||||
|
@ -957,20 +957,15 @@ static void server_parameter_free(SERVER_PARAM *tofree)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a parameter value from a server
|
* Same as server_get_parameter but doesn't lock the server
|
||||||
*
|
*
|
||||||
* @param server The server we are looking for a parameter of
|
* @note Should only be called when the server is already locked
|
||||||
* @param name The name of the parameter we require
|
|
||||||
* @param out Buffer where value is stored, use NULL to check if the parameter exists
|
|
||||||
* @param size Size of @c out, ignored if @c out is NULL
|
|
||||||
*
|
|
||||||
* @return Length of the parameter value or 0 if parameter was not found
|
|
||||||
*/
|
*/
|
||||||
size_t server_get_parameter(const SERVER *server, const char *name, char* out, size_t size)
|
size_t server_get_parameter_nolock(const SERVER *server, const char *name, char* out, size_t size)
|
||||||
{
|
{
|
||||||
int len = 0;
|
ss_dassert(SPINLOCK_IS_LOCKED(server->lock));
|
||||||
|
size_t len = 0;
|
||||||
SERVER_PARAM *param = server->parameters;
|
SERVER_PARAM *param = server->parameters;
|
||||||
spinlock_acquire(&server->lock);
|
|
||||||
|
|
||||||
while (param)
|
while (param)
|
||||||
{
|
{
|
||||||
@ -982,6 +977,23 @@ size_t server_get_parameter(const SERVER *server, const char *name, char* out, s
|
|||||||
param = param->next;
|
param = param->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a parameter value from a server
|
||||||
|
*
|
||||||
|
* @param server The server we are looking for a parameter of
|
||||||
|
* @param name The name of the parameter we require
|
||||||
|
* @param out Buffer where value is stored, use NULL to check if the parameter exists
|
||||||
|
* @param size Size of @c out, ignored if @c out is NULL
|
||||||
|
*
|
||||||
|
* @return Length of the parameter value or 0 if parameter was not found
|
||||||
|
*/
|
||||||
|
size_t server_get_parameter(const SERVER *server, const char *name, char* out, size_t size)
|
||||||
|
{
|
||||||
|
spinlock_acquire(&server->lock);
|
||||||
|
size_t len = server_get_parameter_nolock(server, name, out, size);
|
||||||
spinlock_release(&server->lock);
|
spinlock_release(&server->lock);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -695,7 +695,7 @@ static MXS_MONITORED_SERVER *get_candidate_master(MXS_MONITOR* mon)
|
|||||||
|
|
||||||
moitor_servers->server->depth = 0;
|
moitor_servers->server->depth = 0;
|
||||||
char buf[50]; // Enough to hold most numbers
|
char buf[50]; // Enough to hold most numbers
|
||||||
if (handle->use_priority && server_get_parameter(moitor_servers->server, "priority", buf, sizeof(buf)))
|
if (handle->use_priority && server_get_parameter_nolock(moitor_servers->server, "priority", buf, sizeof(buf)))
|
||||||
{
|
{
|
||||||
/** The server has a priority */
|
/** The server has a priority */
|
||||||
if ((currval = atoi(buf)) > 0)
|
if ((currval = atoi(buf)) > 0)
|
||||||
@ -712,7 +712,7 @@ static MXS_MONITORED_SERVER *get_candidate_master(MXS_MONITOR* mon)
|
|||||||
(!handle->use_priority || /** Server priority disabled*/
|
(!handle->use_priority || /** Server priority disabled*/
|
||||||
candidate_master == NULL || /** No candidate chosen */
|
candidate_master == NULL || /** No candidate chosen */
|
||||||
/** Candidate has no priority */
|
/** Candidate has no priority */
|
||||||
!server_get_parameter(moitor_servers->server, "priority", buf, sizeof(buf))))
|
!server_get_parameter_nolock(moitor_servers->server, "priority", buf, sizeof(buf))))
|
||||||
{
|
{
|
||||||
if (min_id < 0 || moitor_servers->server->node_id < min_id)
|
if (min_id < 0 || moitor_servers->server->node_id < min_id)
|
||||||
{
|
{
|
||||||
@ -848,7 +848,7 @@ static void update_sst_donor_nodes(MXS_MONITOR *mon, int is_cluster)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (handle->use_priority &&
|
if (handle->use_priority &&
|
||||||
server_get_parameter(ptr->server, "priority", NULL, 0))
|
server_get_parameter_nolock(ptr->server, "priority", NULL, 0))
|
||||||
{
|
{
|
||||||
ignore_priority = false;
|
ignore_priority = false;
|
||||||
}
|
}
|
||||||
@ -983,8 +983,8 @@ static int compare_node_priority (const void *a, const void *b)
|
|||||||
const MXS_MONITORED_SERVER *s_b = *(MXS_MONITORED_SERVER * const *)b;
|
const MXS_MONITORED_SERVER *s_b = *(MXS_MONITORED_SERVER * const *)b;
|
||||||
char pri_a[50];
|
char pri_a[50];
|
||||||
char pri_b[50];
|
char pri_b[50];
|
||||||
bool have_a = server_get_parameter(s_a->server, "priority", pri_a, sizeof(pri_a));
|
bool have_a = server_get_parameter_nolock(s_a->server, "priority", pri_a, sizeof(pri_a));
|
||||||
bool have_b = server_get_parameter(s_b->server, "priority", pri_b, sizeof(pri_b));
|
bool have_b = server_get_parameter_nolock(s_b->server, "priority", pri_b, sizeof(pri_b));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check priority parameter:
|
* Check priority parameter:
|
||||||
|
Reference in New Issue
Block a user