Global lock for MySQL Connector's get_driver_instance

See note in https://dev.mysql.com/doc/connector-cpp/1.1/en/connector-cpp-examples-connecting.html

> get_mysql_driver_instance() calls get_driver_instance(), which is not
> thread-safe. Either avoid invoking these methods from within multiple
> threads at once, or surround the calls with a mutex to prevent
> simultaneous execution in multiple threads.
This commit is contained in:
Dennis Felsing 2018-08-27 09:42:34 +02:00
parent 48d1757793
commit 4d634bb7fd
4 changed files with 41 additions and 6 deletions

View file

@ -292,6 +292,8 @@ CServer::CServer()
#endif
#if defined (CONF_SQL)
m_GlobalSqlLock = lock_create();
for (int i = 0; i < MAX_SQLSERVERS; i++)
{
m_apSqlReadServers[i] = 0;
@ -307,6 +309,13 @@ CServer::CServer()
Init();
}
CServer::~CServer()
{
#if defined (CONF_SQL)
lock_destroy(m_GlobalSqlLock);
#endif
}
int CServer::TrySetClientName(int ClientID, const char *pName)
{
char aTrimmedName[64];
@ -2529,7 +2538,7 @@ void CServer::ConAddSqlServer(IConsole::IResult *pResult, void *pUserData)
{
if (!apSqlServers[i])
{
apSqlServers[i] = new CSqlServer(pResult->GetString(1), pResult->GetString(2), pResult->GetString(3), pResult->GetString(4), pResult->GetString(5), pResult->GetInteger(6), ReadOnly, SetUpDb);
apSqlServers[i] = new CSqlServer(pResult->GetString(1), pResult->GetString(2), pResult->GetString(3), pResult->GetString(4), pResult->GetString(5), pResult->GetInteger(6), pSelf->m_GlobalSqlLock, ReadOnly, SetUpDb);
if(SetUpDb)
{

View file

@ -91,6 +91,7 @@ class CServer : public IServer
class IStorage *m_pStorage;
#if defined(CONF_SQL)
LOCK m_GlobalSqlLock;
CSqlServer *m_apSqlReadServers[MAX_SQLSERVERS];
CSqlServer *m_apSqlWriteServers[MAX_SQLSERVERS];
#endif
@ -227,6 +228,7 @@ public:
array<CNameBan> m_aNameBans;
CServer();
~CServer();
int TrySetClientName(int ClientID, const char *pName);

View file

@ -10,9 +10,10 @@
int CSqlServer::ms_NumReadServer = 0;
int CSqlServer::ms_NumWriteServer = 0;
CSqlServer::CSqlServer(const char *pDatabase, const char *pPrefix, const char *pUser, const char *pPass, const char *pIp, int Port, bool ReadOnly, bool SetUpDb) :
CSqlServer::CSqlServer(const char *pDatabase, const char *pPrefix, const char *pUser, const char *pPass, const char *pIp, int Port, LOCK &GlobalLock, bool ReadOnly, bool SetUpDb) :
m_Port(Port),
m_SetUpDB(SetUpDb)
m_SetUpDB(SetUpDb),
m_GlobalLock(GlobalLock)
{
str_copy(m_aDatabase, pDatabase, sizeof(m_aDatabase));
str_copy(m_aPrefix, pPrefix, sizeof(m_aPrefix));
@ -28,6 +29,7 @@ CSqlServer::CSqlServer(const char *pDatabase, const char *pPrefix, const char *p
ReadOnly ? ms_NumReadServer++ : ms_NumWriteServer++;
m_SqlLock = lock_create();
m_GlobalLock = GlobalLock;
}
CSqlServer::~CSqlServer()
@ -91,8 +93,8 @@ bool CSqlServer::Connect()
dbg_msg("sql", "Unknown Error cause by the MySQL/C++ Connector");
}
dbg_msg("sql", "ERROR: SQL connection failed");
UnLock();
dbg_msg("sql", "ERROR: SQL connection failed");
return false;
}
@ -114,7 +116,10 @@ bool CSqlServer::Connect()
connection_properties["OPT_CHARSET_NAME"] = sql::SQLString("utf8mb4");
// Create connection
m_pDriver = get_driver_instance();
{
LockScope globalLock(m_GlobalLock);
m_pDriver = get_driver_instance();
}
m_pConnection = m_pDriver->connect(connection_properties);
// Create Statement

View file

@ -7,10 +7,28 @@
#include <cppconn/exception.h>
#include <cppconn/statement.h>
class LockScope
{
public:
LockScope(LOCK &Lock) :
m_Lock(Lock)
{
lock_wait(m_Lock);
}
~LockScope()
{
lock_unlock(m_Lock);
}
private:
LOCK &m_Lock;
};
class CSqlServer
{
public:
CSqlServer(const char *pDatabase, const char *pPrefix, const char *pUser, const char *pPass, const char *pIp, int Port, bool ReadOnly = true, bool SetUpDb = false);
CSqlServer(const char *pDatabase, const char *pPrefix, const char *pUser, const char *pPass, const char *pIp, int Port, LOCK &GlobalLock, bool ReadOnly = true, bool SetUpDb = false);
~CSqlServer();
bool Connect();
@ -52,6 +70,7 @@ private:
bool m_SetUpDB;
LOCK m_SqlLock;
LOCK &m_GlobalLock;
};
#endif