From f6b8fe10c318d6987826c7bcc0b145eac4c31f0d Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Fri, 8 Oct 2021 10:20:23 +0200 Subject: [PATCH] Fix for CONC-568: If multiple threads attempt to connect to a server using a dynamically loaded authentication plugin the error "plugin is already loaded" might occur. This is caused by a race condition if one thread waits for a lock to load the plugin, while another process which obtained the lock already loaded the plugin. The API function mysql_load_plugin_v() now returns the plugin handle (instead of raising an error and returning a NULL handle) even if the plugin was already loaded. --- libmariadb/ma_client_plugin.c.in | 14 ++++---------- libmariadb/mariadb_lib.c | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/libmariadb/ma_client_plugin.c.in b/libmariadb/ma_client_plugin.c.in index b635f21d..dc4fd4e7 100755 --- a/libmariadb/ma_client_plugin.c.in +++ b/libmariadb/ma_client_plugin.c.in @@ -330,6 +330,7 @@ struct st_mysql_client_plugin * STDCALL mysql_client_register_plugin(MYSQL *mysql, struct st_mysql_client_plugin *plugin) { + struct st_mysql_client_plugin *found_plugin= NULL; va_list unused; LINT_INIT_STRUCT(unused); @@ -339,18 +340,11 @@ mysql_client_register_plugin(MYSQL *mysql, pthread_mutex_lock(&LOCK_load_client_plugin); /* make sure the plugin wasn't loaded meanwhile */ - if (find_plugin(plugin->name, plugin->type)) - { - my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, - SQLSTATE_UNKNOWN, ER(CR_AUTH_PLUGIN_CANNOT_LOAD), - plugin->name, "it is already loaded"); - plugin= NULL; - } - else - plugin= add_plugin(mysql, plugin, 0, 0, unused); + if (!(found_plugin= find_plugin(plugin->name, plugin->type))) + found_plugin= add_plugin(mysql, plugin, 0, 0, unused); pthread_mutex_unlock(&LOCK_load_client_plugin); - return plugin; + return found_plugin; } diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 9c9279ef..389ec5bc 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -4060,7 +4060,7 @@ my_bool mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ... *((char **)arg)= (char *)ma_pvio_tls_cipher(mysql->net.pvio->ctls); else #endif - goto error; + *((char **)arg)= NULL; break; case MARIADB_CLIENT_ERRORS: *((char ***)arg)= (char **)client_errors;