From b33695a2efe9401548faec150c677209858549e8 Mon Sep 17 00:00:00 2001 From: jackpoz Date: Fri, 3 Oct 2014 21:21:17 +0200 Subject: [PATCH] Core/Worldserver: Fix worldserver stuck on "Halting process" on shutdown Partially revert 4fe45b8c63d3c4118a0a69c6ed44573c53eba54c to fix worldserver stuck on "Halting process" on shutdown. Fixes #13201 --- src/server/worldserver/Main.cpp | 83 ++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index bd028069c62..6c93343b8de 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -88,6 +88,7 @@ bool StartDB(); void StopDB(); void WorldUpdateLoop(); void ClearOnlineAccounts(); +void ShutdownCLIThread(std::thread* cliThread); void ShutdownThreadPool(std::vector& threadPool); variables_map GetConsoleArguments(int argc, char** argv, std::string& cfg_file, std::string& cfg_service); @@ -277,27 +278,7 @@ extern int main(int argc, char** argv) TC_LOG_INFO("server.worldserver", "Halting process..."); - if (cliThread != nullptr) - { -#ifdef _WIN32 - if (!CancelSynchronousIo(cliThread->native_handle())) - { - DWORD errorCode = GetLastError(); - LPSTR errorBuffer; - - DWORD formatReturnCode = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, errorCode, 0, (LPTSTR)&errorBuffer, 0, nullptr); - if (!formatReturnCode) - errorBuffer = "Unknown error"; - - TC_LOG_ERROR("server.worldserver", "Error cancelling I/O of CliThread, error code %u, detail: %s", - errorCode, errorBuffer); - LocalFree(errorBuffer); - } -#endif - cliThread->join(); - delete cliThread; - } + ShutdownCLIThread(cliThread); OpenSSLCrypto::threadsCleanup(); @@ -308,6 +289,66 @@ extern int main(int argc, char** argv) return World::GetExitCode(); } +void ShutdownCLIThread(std::thread* cliThread) +{ + if (cliThread != nullptr) + { +#ifdef _WIN32 + // First try to cancel any I/O in the CLI thread + if (!CancelSynchronousIo(cliThread->native_handle())) + { + // if CancelSynchronousIo() fails, print the error and try with old way + DWORD errorCode = GetLastError(); + LPSTR errorBuffer; + + DWORD formatReturnCode = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, errorCode, 0, (LPTSTR)&errorBuffer, 0, nullptr); + if (!formatReturnCode) + errorBuffer = "Unknown error"; + + TC_LOG_DEBUG("server.worldserver", "Error cancelling I/O of CliThread, error code %u, detail: %s", + errorCode, errorBuffer); + LocalFree(errorBuffer); + + // send keyboard input to safely unblock the CLI thread + INPUT_RECORD b[4]; + HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); + b[0].EventType = KEY_EVENT; + b[0].Event.KeyEvent.bKeyDown = TRUE; + b[0].Event.KeyEvent.uChar.AsciiChar = 'X'; + b[0].Event.KeyEvent.wVirtualKeyCode = 'X'; + b[0].Event.KeyEvent.wRepeatCount = 1; + + b[1].EventType = KEY_EVENT; + b[1].Event.KeyEvent.bKeyDown = FALSE; + b[1].Event.KeyEvent.uChar.AsciiChar = 'X'; + b[1].Event.KeyEvent.wVirtualKeyCode = 'X'; + b[1].Event.KeyEvent.wRepeatCount = 1; + + b[2].EventType = KEY_EVENT; + b[2].Event.KeyEvent.bKeyDown = TRUE; + b[2].Event.KeyEvent.dwControlKeyState = 0; + b[2].Event.KeyEvent.uChar.AsciiChar = '\r'; + b[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; + b[2].Event.KeyEvent.wRepeatCount = 1; + b[2].Event.KeyEvent.wVirtualScanCode = 0x1c; + + b[3].EventType = KEY_EVENT; + b[3].Event.KeyEvent.bKeyDown = FALSE; + b[3].Event.KeyEvent.dwControlKeyState = 0; + b[3].Event.KeyEvent.uChar.AsciiChar = '\r'; + b[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; + b[3].Event.KeyEvent.wVirtualScanCode = 0x1c; + b[3].Event.KeyEvent.wRepeatCount = 1; + DWORD numb; + WriteConsoleInput(hStdIn, b, 4, &numb); + } +#endif + cliThread->join(); + delete cliThread; + } +} + void ShutdownThreadPool(std::vector& threadPool) { sScriptMgr->OnNetworkStop();