Core/Database: Change database async thread shutdown to fix some corner cases leading to servers being stuck on shutdown (for example with exit() call)

(cherry picked from commit 11a832fa8b)
This commit is contained in:
Shauren
2024-09-19 13:38:49 +02:00
committed by Ovahlord
parent 249d1372bb
commit 3cde083745
2 changed files with 15 additions and 7 deletions

View File

@@ -47,6 +47,12 @@ MySQLConnectionInfo::MySQLConnectionInfo(std::string const& infoString)
ssl.assign(tokens[5]);
}
struct MySQLConnection::WorkerThread
{
std::thread ThreadHandle;
boost::asio::executor_work_guard<Trinity::Asio::IoContext::Executor> WorkGuard;
};
MySQLConnection::MySQLConnection(MySQLConnectionInfo& connInfo, ConnectionFlags connectionFlags) :
m_reconnecting(false),
m_prepareError(false),
@@ -66,7 +72,8 @@ void MySQLConnection::Close()
// Stop the worker thread before the statements are cleared
if (m_workerThread)
{
m_workerThread->join();
m_workerThread->WorkGuard.reset();
m_workerThread->ThreadHandle.join();
m_workerThread.reset();
}
@@ -444,18 +451,18 @@ uint32 MySQLConnection::GetLastError()
void MySQLConnection::StartWorkerThread(Trinity::Asio::IoContext* context)
{
m_workerThread = std::make_unique<std::thread>([context]
{
boost::asio::executor_work_guard executorWorkGuard = boost::asio::make_work_guard(context->get_executor());
boost::asio::executor_work_guard executorWorkGuard = boost::asio::make_work_guard(context->get_executor()); // construct guard before thread starts running
context->run();
m_workerThread = std::make_unique<WorkerThread>(WorkerThread{
.ThreadHandle = std::thread([context] { context->run(); }),
.WorkGuard = std::move(executorWorkGuard)
});
}
std::thread::id MySQLConnection::GetWorkerThreadId() const
{
if (m_workerThread)
return m_workerThread->get_id();
return m_workerThread->ThreadHandle.get_id();
return {};
}

View File

@@ -104,7 +104,8 @@ class TC_DATABASE_API MySQLConnection
private:
bool _HandleMySQLErrno(uint32 errNo, uint8 attempts = 5);
std::unique_ptr<std::thread> m_workerThread; //!< Core worker thread.
struct WorkerThread;
std::unique_ptr<WorkerThread> m_workerThread; //!< Core worker thread.
MySQLHandle* m_Mysql; //!< MySQL Handle.
MySQLConnectionInfo& m_connectionInfo; //!< Connection info (used for logging)
ConnectionFlags m_connectionFlags; //!< Connection flags (for preparing relevant statements)