mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-02-16 02:30:54 +00:00
Fix race condition in debug build printing
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user