Fix race condition in debug build printing

This commit is contained in:
Lion Kortlepel
2020-11-04 11:58:09 +01:00
parent 2beff2495f
commit 5452aeb558
3 changed files with 69 additions and 54 deletions

View File

@@ -2,8 +2,10 @@
/// Created by Anonymous275 on 4/2/2020. /// Created by Anonymous275 on 4/2/2020.
/// ///
#pragma once #pragma once
#include <string>
#include <iostream> #include <iostream>
#include <mutex>
#include <string>
extern std::mutex MLock;
void InitLog(); void InitLog();
#define DebugPrintTID() DebugPrintTIDInternal(__func__) #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 void DebugPrintTIDInternal(const std::string& func); // prints the current thread id in debug mode, to make tracing of crashes and asserts easier

View File

@@ -4,8 +4,8 @@
#include "Lua/LuaSystem.hpp" #include "Lua/LuaSystem.hpp"
#ifdef WIN32 #ifdef WIN32
#include <windows.h>
#include <conio.h> #include <conio.h>
#include <windows.h>
#else // *nix #else // *nix
typedef unsigned long DWORD, *PDWORD, *LPDWORD; typedef unsigned long DWORD, *PDWORD, *LPDWORD;
#include <termios.h> #include <termios.h>
@@ -13,27 +13,30 @@ typedef unsigned long DWORD, *PDWORD, *LPDWORD;
#endif // WIN32 #endif // WIN32
#include "Logger.h" #include "Logger.h"
#include <iostream> #include <iostream>
#include <mutex>
#include <string> #include <string>
#include <thread> #include <thread>
#include <mutex>
std::vector<std::string> QConsoleOut; std::vector<std::string> QConsoleOut;
std::string CInputBuff; std::string CInputBuff;
std::mutex MLock; std::mutex MLock;
Lua* LuaConsole; Lua* LuaConsole;
void HandleInput(const std::string& cmd){ void HandleInput(const std::string& cmd) {
std::cout << std::endl; std::cout << std::endl;
if (cmd == "exit") { if (cmd == "exit") {
exit(0); exit(0);
}else LuaConsole->Execute(cmd); } else
LuaConsole->Execute(cmd);
} }
void ProcessOut(){ void ProcessOut() {
static size_t len = 2; static size_t len = 2;
if(QConsoleOut.empty() && len == CInputBuff.length())return; if (QConsoleOut.empty() && len == CInputBuff.length())
return;
printf("%c[2K\r", 27); printf("%c[2K\r", 27);
for(const std::string& msg : QConsoleOut) for (const std::string& msg : QConsoleOut)
if(!msg.empty())std::cout << msg; if (!msg.empty())
std::cout << msg;
MLock.lock(); MLock.lock();
QConsoleOut.clear(); QConsoleOut.clear();
MLock.unlock(); MLock.unlock();
@@ -41,55 +44,54 @@ void ProcessOut(){
len = CInputBuff.length(); len = CInputBuff.length();
} }
void ConsoleOut(const std::string& msg){ void ConsoleOut(const std::string& msg) {
MLock.lock(); MLock.lock();
QConsoleOut.emplace_back(msg); QConsoleOut.emplace_back(msg);
MLock.unlock(); MLock.unlock();
} }
[[noreturn]] void OutputRefresh(){ [[noreturn]] void OutputRefresh() {
DebugPrintTID(); DebugPrintTID();
while(true){ while (true) {
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
ProcessOut(); ProcessOut();
} }
} }
#ifndef WIN32 #ifndef WIN32
static int _getch() static int _getch() {
{
char buf = 0; char buf = 0;
struct termios old; struct termios old;
fflush(stdout); fflush(stdout);
if(tcgetattr(0, &old) < 0) if (tcgetattr(0, &old) < 0)
perror("tcsetattr()"); perror("tcsetattr()");
old.c_lflag &= ~unsigned(ICANON); old.c_lflag &= ~unsigned(ICANON);
old.c_lflag &= ~unsigned(ECHO); old.c_lflag &= ~unsigned(ECHO);
old.c_cc[VMIN] = 1; old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0; old.c_cc[VTIME] = 0;
if(tcsetattr(0, TCSANOW, &old) < 0) if (tcsetattr(0, TCSANOW, &old) < 0)
perror("tcsetattr ICANON"); perror("tcsetattr ICANON");
if(read(0, &buf, 1) < 0) if (read(0, &buf, 1) < 0)
perror("read()"); perror("read()");
old.c_lflag |= ICANON; old.c_lflag |= ICANON;
old.c_lflag |= ECHO; old.c_lflag |= ECHO;
if(tcsetattr(0, TCSADRAIN, &old) < 0) if (tcsetattr(0, TCSADRAIN, &old) < 0)
perror("tcsetattr ~ICANON"); perror("tcsetattr ~ICANON");
// no echo printf("%c\n", buf); // no echo printf("%c\n", buf);
return buf; return buf;
} }
#endif // WIN32 #endif // WIN32
void SetupConsole(){ void SetupConsole() {
#ifdef WIN32 #ifdef WIN32
DWORD outMode = 0; DWORD outMode = 0;
HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if (stdoutHandle == INVALID_HANDLE_VALUE){ if (stdoutHandle == INVALID_HANDLE_VALUE) {
error("Invalid handle"); error("Invalid handle");
std::this_thread::sleep_for(std::chrono::seconds(3)); std::this_thread::sleep_for(std::chrono::seconds(3));
exit(GetLastError()); exit(GetLastError());
} }
if (!GetConsoleMode(stdoutHandle, &outMode)){ if (!GetConsoleMode(stdoutHandle, &outMode)) {
error("Invalid console mode"); error("Invalid console mode");
std::this_thread::sleep_for(std::chrono::seconds(3)); std::this_thread::sleep_for(std::chrono::seconds(3));
exit(GetLastError()); exit(GetLastError());
@@ -105,27 +107,28 @@ void SetupConsole(){
#endif // WIN32 #endif // WIN32
} }
[[noreturn]] void ReadCin(){ [[noreturn]] void ReadCin() {
DebugPrintTID(); DebugPrintTID();
while (true){ while (true) {
int In = _getch(); int In = _getch();
if (In == 13 || In == '\n') { if (In == 13 || In == '\n') {
if(!CInputBuff.empty()) { if (!CInputBuff.empty()) {
HandleInput(CInputBuff); HandleInput(CInputBuff);
CInputBuff.clear(); CInputBuff.clear();
} }
}else if(In == 8){ } else if (In == 8) {
if(!CInputBuff.empty())CInputBuff.pop_back(); if (!CInputBuff.empty())
CInputBuff.pop_back();
} else if (In == 4) { } else if (In == 4) {
CInputBuff = "exit"; CInputBuff = "exit";
HandleInput(CInputBuff); HandleInput(CInputBuff);
CInputBuff.clear(); CInputBuff.clear();
}else { } else {
CInputBuff += char(In); CInputBuff += char(In);
} }
} }
} }
void ConsoleInit(){ void ConsoleInit() {
SetupConsole(); SetupConsole();
LuaConsole = new Lua(); LuaConsole = new Lua();
LuaConsole->Console = true; LuaConsole->Console = true;

View File

@@ -1,20 +1,23 @@
/// ///
/// Created by Anonymous275 on 7/17/2020 /// Created by Anonymous275 on 7/17/2020
/// ///
#include "Logger.h"
#include "Security/Enc.h" #include "Security/Enc.h"
#include "Settings.h" #include "Settings.h"
#include "Logger.h"
#include <fstream>
#include <sstream>
#include <chrono> #include <chrono>
#include <fstream>
#include <mutex> #include <mutex>
#include <sstream>
#include <thread> #include <thread>
void DebugPrintTIDInternal(const std::string& func) { void DebugPrintTIDInternal(const std::string& func) {
// we need to print to cout here as we might crash before all console output is handled, // we need to print to cout here as we might crash before all console output is handled,
// due to segfaults or asserts. // due to segfaults or asserts.
#ifdef DEBUG #ifdef DEBUG
MLock.lock();
printf("%c[2K\r", 27);
std::cout << "(debug build) Thread '" << std::this_thread::get_id() << "' is " << func << std::endl; std::cout << "(debug build) Thread '" << std::this_thread::get_id() << "' is " << func << std::endl;
MLock.unlock();
#endif // DEBUG #endif // DEBUG
} }
@@ -22,14 +25,18 @@ std::string getDate() {
typedef std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>::type> days; typedef std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>::type> days;
std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::chrono::system_clock::duration tp = now.time_since_epoch(); std::chrono::system_clock::duration tp = now.time_since_epoch();
days d = std::chrono::duration_cast<days>(tp);tp -= d; days d = std::chrono::duration_cast<days>(tp);
auto h = std::chrono::duration_cast<std::chrono::hours>(tp);tp -= h; tp -= d;
auto m = std::chrono::duration_cast<std::chrono::minutes>(tp);tp -= m; auto h = std::chrono::duration_cast<std::chrono::hours>(tp);
auto s = std::chrono::duration_cast<std::chrono::seconds>(tp);tp -= s; tp -= h;
auto m = std::chrono::duration_cast<std::chrono::minutes>(tp);
tp -= m;
auto s = std::chrono::duration_cast<std::chrono::seconds>(tp);
tp -= s;
time_t tt = std::chrono::system_clock::to_time_t(now); time_t tt = std::chrono::system_clock::to_time_t(now);
tm local_tm{}; tm local_tm {};
#ifdef WIN32 #ifdef WIN32
localtime_s(&local_tm,&tt); localtime_s(&local_tm, &tt);
#else // unix #else // unix
localtime_r(&tt, &local_tm); localtime_r(&tt, &local_tm);
#endif // WIN32 #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 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)); std::string Hour = (H > 9 ? std::to_string(H) : "0" + std::to_string(H));
date date
<< "[" << "["
<< local_tm.tm_mday << "/" << local_tm.tm_mday << "/"
<< local_tm.tm_mon + 1 << "/" << local_tm.tm_mon + 1 << "/"
<< local_tm.tm_year + 1900 << " " << local_tm.tm_year + 1900 << " "
<< Hour << ":" << Hour << ":"
<< Min << ":" << Min << ":"
<< Secs << Secs
<< "] "; << "] ";
return date.str(); return date.str();
} }
void InitLog(){ void InitLog() {
std::ofstream LFS; std::ofstream LFS;
LFS.open (Sec("Server.log")); LFS.open(Sec("Server.log"));
if(!LFS.is_open()){ if (!LFS.is_open()) {
error(Sec("logger file init failed!")); error(Sec("logger file init failed!"));
}else LFS.close(); } else
LFS.close();
} }
std::mutex LogLock; std::mutex LogLock;
void addToLog(const std::string& Line){ void addToLog(const std::string& Line) {
std::ofstream LFS; 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 << Line.c_str();
LFS.close(); LFS.close();
} }
@@ -73,14 +81,15 @@ void info(const std::string& toPrint) {
LogLock.unlock(); LogLock.unlock();
} }
void debug(const std::string& toPrint) { void debug(const std::string& toPrint) {
if(!Debug)return; if (!Debug)
return;
LogLock.lock(); LogLock.lock();
std::string Print = getDate() + Sec("[DEBUG] ") + toPrint + "\n"; std::string Print = getDate() + Sec("[DEBUG] ") + toPrint + "\n";
ConsoleOut(Print); ConsoleOut(Print);
addToLog(Print); addToLog(Print);
LogLock.unlock(); LogLock.unlock();
} }
void warn(const std::string& toPrint){ void warn(const std::string& toPrint) {
LogLock.lock(); LogLock.lock();
std::string Print = getDate() + Sec("[WARN] ") + toPrint + "\n"; std::string Print = getDate() + Sec("[WARN] ") + toPrint + "\n";
ConsoleOut(Print); ConsoleOut(Print);
@@ -93,7 +102,8 @@ void error(const std::string& toPrint) {
std::string Print = getDate() + Sec("[ERROR] ") + toPrint + "\n"; std::string Print = getDate() + Sec("[ERROR] ") + toPrint + "\n";
ConsoleOut(Print); ConsoleOut(Print);
addToLog(Print); addToLog(Print);
if(ECounter > 10)exit(7); if (ECounter > 10)
exit(7);
ECounter++; ECounter++;
LogLock.unlock(); LogLock.unlock();
} }