Switch database mutex to recursive because we copy it everywhere

... and I have no idea if any of the calls are re-entrant. yay.
This commit is contained in:
brainiac 2026-04-04 17:34:59 -07:00
parent 7aa669d041
commit d1d5c5dd7a
8 changed files with 17 additions and 16 deletions

View File

@ -34,7 +34,7 @@
DBcore::DBcore()
: mysql(mysql_init(nullptr))
, m_mutex(std::make_shared<std::mutex>())
, m_mutex(std::make_shared<Mutex>())
{
}
@ -220,12 +220,12 @@ bool DBcore::Open(
bool DBcore::Open(uint32 *errnum, char *errbuf)
{
// Expects m_mutex to already be locked.
if (errbuf) {
errbuf[0] = 0;
}
std::scoped_lock lock(*m_mutex);
if (GetStatus() == Connected) {
return true;
}
@ -294,7 +294,7 @@ std::string DBcore::Escape(const std::string& s)
return temp.data();
}
void DBcore::SetMutex(const std::shared_ptr<std::mutex>& mutex)
void DBcore::SetMutex(const std::shared_ptr<Mutex>& mutex)
{
DBcore::m_mutex = mutex;
}

View File

@ -36,6 +36,8 @@ public:
Closed, Connected, Error
};
using Mutex = std::recursive_mutex;
DBcore();
~DBcore();
eStatus GetStatus() { return pStatus; }
@ -59,7 +61,7 @@ public:
mysql = o.mysql;
mysqlOwner = false;
}
void SetMutex(const std::shared_ptr<std::mutex>& mutex);
void SetMutex(const std::shared_ptr<Mutex>& mutex);
// only safe on connections shared with other threads if results buffered
// unsafe to use off main thread due to internal server logging
@ -86,8 +88,7 @@ private:
bool mysqlOwner = true;
eStatus pStatus = Closed;
std::shared_ptr<std::mutex> m_mutex;
std::mutex m_query_lock;
std::shared_ptr<Mutex> m_mutex;
std::string origin_host;

View File

@ -95,7 +95,7 @@ void TaskScheduler::ProcessWork()
m_data->cv.wait(lock,
[this]
{
return !m_data->running || m_data->tasks.empty();
return !m_data->running || !m_data->tasks.empty();
});
if (!m_data->running)

View File

@ -35,7 +35,7 @@ void PreparedStmt::StmtDeleter::operator()(MYSQL_STMT* stmt) noexcept
mysql_stmt_close(stmt);
}
PreparedStmt::PreparedStmt(MYSQL& mysql, std::string query, std::mutex& mutex, StmtOptions opts)
PreparedStmt::PreparedStmt(MYSQL& mysql, std::string query, DBcore::Mutex& mutex, StmtOptions opts)
: m_stmt(mysql_stmt_init(&mysql), { mutex })
, m_query(std::move(query))
, m_options(opts)

View File

@ -17,8 +17,8 @@
*/
#pragma once
#include "common/dbcore.h"
#include "mysql.h"
#include <cassert>
#include <cstring>
#include <memory>
@ -185,7 +185,7 @@ public:
int64_t, uint64_t, float, double, bool, std::string_view, std::nullptr_t>;
PreparedStmt() = delete;
PreparedStmt(MYSQL& mysql, std::string query, std::mutex& mutex, StmtOptions opts = {});
PreparedStmt(MYSQL& mysql, std::string query, DBcore::Mutex& mutex, StmtOptions opts = {});
const std::string& GetQuery() const { return m_query; }
StmtOptions GetOptions() const { return m_options; }
@ -221,7 +221,7 @@ private:
struct StmtDeleter
{
std::mutex& mutex;
DBcore::Mutex& mutex;
void operator()(MYSQL_STMT* stmt) noexcept;
};
@ -235,7 +235,7 @@ private:
std::string m_query;
StmtOptions m_options = {};
bool m_need_bind = true;
std::mutex& m_mutex; // connection mutex
DBcore::Mutex& m_mutex; // connection mutex
};
} // namespace mysql

View File

@ -76,7 +76,7 @@ void WorldserverCLI::TestDatabaseConcurrency(int argc, char **argv, argh::parser
return;
}
std::shared_ptr<std::mutex> sharedMutex = std::make_shared<std::mutex>();
std::shared_ptr<DBcore::Mutex> sharedMutex = std::make_shared<DBcore::Mutex>();
db.SetMutex(sharedMutex);

View File

@ -180,7 +180,7 @@ bool WorldBoot::LoadDatabaseConnections()
// when database and content_db share the same underlying mysql connection
// it needs to be protected by a shared mutex otherwise we produce concurrency issues
// when database actions are occurring in different threads
std::shared_ptr<std::mutex> sharedMutex = std::make_shared<std::mutex>();
std::shared_ptr<DBcore::Mutex> sharedMutex = std::make_shared<DBcore::Mutex>();
database.SetMutex(sharedMutex);
content_db.SetMutex(sharedMutex);
}

View File

@ -246,7 +246,7 @@ int main(int argc, char **argv)
// when database and content_db share the same underlying mysql connection
// it needs to be protected by a shared mutex otherwise we produce concurrency issues
// when database actions are occurring in different threads
std::shared_ptr<std::mutex> sharedMutex = std::make_shared<std::mutex>();
std::shared_ptr<DBcore::Mutex> sharedMutex = std::make_shared<DBcore::Mutex>();
database.SetMutex(sharedMutex);
content_db.SetMutex(sharedMutex);
}