From 5452aeb5586bfeaa8a35719d51eeaa09d5e3d779 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Wed, 4 Nov 2020 11:58:09 +0100 Subject: [PATCH] Fix race condition in debug build printing --- include/Logger.h | 4 +++- src/Console.cpp | 57 +++++++++++++++++++++++--------------------- src/logger.cpp | 62 ++++++++++++++++++++++++++++-------------------- 3 files changed, 69 insertions(+), 54 deletions(-) diff --git a/include/Logger.h b/include/Logger.h index fa05349..93d4e48 100644 --- a/include/Logger.h +++ b/include/Logger.h @@ -2,8 +2,10 @@ /// Created by Anonymous275 on 4/2/2020. /// #pragma once -#include #include +#include +#include +extern std::mutex MLock; void InitLog(); #define DebugPrintTID() DebugPrintTIDInternal(__func__) void DebugPrintTIDInternal(const std::string& func); // prints the current thread id in debug mode, to make tracing of crashes and asserts easier diff --git a/src/Console.cpp b/src/Console.cpp index 3103da4..4d9ec44 100644 --- a/src/Console.cpp +++ b/src/Console.cpp @@ -4,8 +4,8 @@ #include "Lua/LuaSystem.hpp" #ifdef WIN32 -#include #include +#include #else // *nix typedef unsigned long DWORD, *PDWORD, *LPDWORD; #include @@ -13,27 +13,30 @@ typedef unsigned long DWORD, *PDWORD, *LPDWORD; #endif // WIN32 #include "Logger.h" #include +#include #include #include -#include std::vector QConsoleOut; std::string CInputBuff; std::mutex MLock; Lua* LuaConsole; -void HandleInput(const std::string& cmd){ +void HandleInput(const std::string& cmd) { std::cout << std::endl; if (cmd == "exit") { exit(0); - }else LuaConsole->Execute(cmd); + } else + LuaConsole->Execute(cmd); } -void ProcessOut(){ +void ProcessOut() { static size_t len = 2; - if(QConsoleOut.empty() && len == CInputBuff.length())return; + if (QConsoleOut.empty() && len == CInputBuff.length()) + return; printf("%c[2K\r", 27); - for(const std::string& msg : QConsoleOut) - if(!msg.empty())std::cout << msg; + for (const std::string& msg : QConsoleOut) + if (!msg.empty()) + std::cout << msg; MLock.lock(); QConsoleOut.clear(); MLock.unlock(); @@ -41,55 +44,54 @@ void ProcessOut(){ len = CInputBuff.length(); } -void ConsoleOut(const std::string& msg){ +void ConsoleOut(const std::string& msg) { MLock.lock(); QConsoleOut.emplace_back(msg); MLock.unlock(); } -[[noreturn]] void OutputRefresh(){ +[[noreturn]] void OutputRefresh() { DebugPrintTID(); - while(true){ + while (true) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); ProcessOut(); } } #ifndef WIN32 -static int _getch() -{ +static int _getch() { char buf = 0; struct termios old; fflush(stdout); - if(tcgetattr(0, &old) < 0) + if (tcgetattr(0, &old) < 0) perror("tcsetattr()"); old.c_lflag &= ~unsigned(ICANON); old.c_lflag &= ~unsigned(ECHO); old.c_cc[VMIN] = 1; old.c_cc[VTIME] = 0; - if(tcsetattr(0, TCSANOW, &old) < 0) + if (tcsetattr(0, TCSANOW, &old) < 0) perror("tcsetattr ICANON"); - if(read(0, &buf, 1) < 0) + if (read(0, &buf, 1) < 0) perror("read()"); old.c_lflag |= ICANON; old.c_lflag |= ECHO; - if(tcsetattr(0, TCSADRAIN, &old) < 0) + if (tcsetattr(0, TCSADRAIN, &old) < 0) perror("tcsetattr ~ICANON"); // no echo printf("%c\n", buf); return buf; } #endif // WIN32 -void SetupConsole(){ +void SetupConsole() { #ifdef WIN32 DWORD outMode = 0; HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); - if (stdoutHandle == INVALID_HANDLE_VALUE){ + if (stdoutHandle == INVALID_HANDLE_VALUE) { error("Invalid handle"); std::this_thread::sleep_for(std::chrono::seconds(3)); exit(GetLastError()); } - if (!GetConsoleMode(stdoutHandle, &outMode)){ + if (!GetConsoleMode(stdoutHandle, &outMode)) { error("Invalid console mode"); std::this_thread::sleep_for(std::chrono::seconds(3)); exit(GetLastError()); @@ -105,27 +107,28 @@ void SetupConsole(){ #endif // WIN32 } -[[noreturn]] void ReadCin(){ +[[noreturn]] void ReadCin() { DebugPrintTID(); - while (true){ + while (true) { int In = _getch(); if (In == 13 || In == '\n') { - if(!CInputBuff.empty()) { + if (!CInputBuff.empty()) { HandleInput(CInputBuff); CInputBuff.clear(); } - }else if(In == 8){ - if(!CInputBuff.empty())CInputBuff.pop_back(); + } else if (In == 8) { + if (!CInputBuff.empty()) + CInputBuff.pop_back(); } else if (In == 4) { CInputBuff = "exit"; HandleInput(CInputBuff); CInputBuff.clear(); - }else { + } else { CInputBuff += char(In); } } } -void ConsoleInit(){ +void ConsoleInit() { SetupConsole(); LuaConsole = new Lua(); LuaConsole->Console = true; diff --git a/src/logger.cpp b/src/logger.cpp index 357ebf4..5b9e99a 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -1,20 +1,23 @@ /// /// Created by Anonymous275 on 7/17/2020 /// +#include "Logger.h" #include "Security/Enc.h" #include "Settings.h" -#include "Logger.h" -#include -#include #include +#include #include +#include #include void DebugPrintTIDInternal(const std::string& func) { // we need to print to cout here as we might crash before all console output is handled, // due to segfaults or asserts. #ifdef DEBUG + MLock.lock(); + printf("%c[2K\r", 27); std::cout << "(debug build) Thread '" << std::this_thread::get_id() << "' is " << func << std::endl; + MLock.unlock(); #endif // DEBUG } @@ -22,14 +25,18 @@ std::string getDate() { typedef std::chrono::duration>::type> days; std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); std::chrono::system_clock::duration tp = now.time_since_epoch(); - days d = std::chrono::duration_cast(tp);tp -= d; - auto h = std::chrono::duration_cast(tp);tp -= h; - auto m = std::chrono::duration_cast(tp);tp -= m; - auto s = std::chrono::duration_cast(tp);tp -= s; + days d = std::chrono::duration_cast(tp); + tp -= d; + auto h = std::chrono::duration_cast(tp); + tp -= h; + auto m = std::chrono::duration_cast(tp); + tp -= m; + auto s = std::chrono::duration_cast(tp); + tp -= s; time_t tt = std::chrono::system_clock::to_time_t(now); - tm local_tm{}; + tm local_tm {}; #ifdef WIN32 - localtime_s(&local_tm,&tt); + localtime_s(&local_tm, &tt); #else // unix localtime_r(&tt, &local_tm); #endif // WIN32 @@ -41,27 +48,28 @@ std::string getDate() { std::string Min = (M > 9 ? std::to_string(M) : "0" + std::to_string(M)); std::string Hour = (H > 9 ? std::to_string(H) : "0" + std::to_string(H)); date - << "[" - << local_tm.tm_mday << "/" - << local_tm.tm_mon + 1 << "/" - << local_tm.tm_year + 1900 << " " - << Hour << ":" - << Min << ":" - << Secs - << "] "; + << "[" + << local_tm.tm_mday << "/" + << local_tm.tm_mon + 1 << "/" + << local_tm.tm_year + 1900 << " " + << Hour << ":" + << Min << ":" + << Secs + << "] "; return date.str(); } -void InitLog(){ +void InitLog() { std::ofstream LFS; - LFS.open (Sec("Server.log")); - if(!LFS.is_open()){ + LFS.open(Sec("Server.log")); + if (!LFS.is_open()) { error(Sec("logger file init failed!")); - }else LFS.close(); + } else + LFS.close(); } std::mutex LogLock; -void addToLog(const std::string& Line){ +void addToLog(const std::string& Line) { std::ofstream LFS; - LFS.open (Sec("Server.log"), std::ios_base::app); + LFS.open(Sec("Server.log"), std::ios_base::app); LFS << Line.c_str(); LFS.close(); } @@ -73,14 +81,15 @@ void info(const std::string& toPrint) { LogLock.unlock(); } void debug(const std::string& toPrint) { - if(!Debug)return; + if (!Debug) + return; LogLock.lock(); std::string Print = getDate() + Sec("[DEBUG] ") + toPrint + "\n"; ConsoleOut(Print); addToLog(Print); LogLock.unlock(); } -void warn(const std::string& toPrint){ +void warn(const std::string& toPrint) { LogLock.lock(); std::string Print = getDate() + Sec("[WARN] ") + toPrint + "\n"; ConsoleOut(Print); @@ -93,7 +102,8 @@ void error(const std::string& toPrint) { std::string Print = getDate() + Sec("[ERROR] ") + toPrint + "\n"; ConsoleOut(Print); addToLog(Print); - if(ECounter > 10)exit(7); + if (ECounter > 10) + exit(7); ECounter++; LogLock.unlock(); }