mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-03 08:15:35 +00:00
watchdog system
This commit is contained in:
parent
2355327c21
commit
36699676b5
@ -16,6 +16,7 @@ if (WIN32)
|
||||
endif()
|
||||
|
||||
include_directories("include/sentry-native/include")
|
||||
|
||||
set(SENTRY_BUILD_SHARED_LIBS OFF)
|
||||
if (MSVC)
|
||||
set(SENTRY_BUILD_RUNTIMESTATIC ON)
|
||||
@ -25,6 +26,7 @@ add_subdirectory("include/sentry-native")
|
||||
|
||||
message(STATUS "Setting compiler flags")
|
||||
if (WIN32)
|
||||
add_subdirectory("include/watchdog")
|
||||
#-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
|
||||
set(VcpkgRoot ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET})
|
||||
include_directories(${VcpkgRoot}/include)
|
||||
@ -65,8 +67,7 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
||||
message(STATUS "Looking for Boost")
|
||||
find_package(Boost REQUIRED COMPONENTS system thread)
|
||||
|
||||
add_executable(BeamMP-Server
|
||||
src/main.cpp
|
||||
file(GLOB source_files src/main.cpp
|
||||
include/TConsole.h src/TConsole.cpp
|
||||
include/TServer.h src/TServer.cpp
|
||||
include/Compat.h src/Compat.cpp
|
||||
@ -84,6 +85,8 @@ add_executable(BeamMP-Server
|
||||
include/TNetwork.h src/TNetwork.cpp
|
||||
include/SignalHandling.h src/SignalHandling.cpp)
|
||||
|
||||
add_executable(BeamMP-Server ${source_files})
|
||||
|
||||
target_compile_definitions(BeamMP-Server PRIVATE SECRET_SENTRY_URL="${BEAMMP_SECRET_SENTRY_URL}")
|
||||
|
||||
target_include_directories(BeamMP-Server PUBLIC
|
||||
@ -118,6 +121,11 @@ if (UNIX)
|
||||
sioclient_tls
|
||||
sentry)
|
||||
elseif (WIN32)
|
||||
set_source_files_properties(${source_files} PROPERTIES COMPILE_FLAGS "/Gh /GH")
|
||||
add_compile_options("$<$<NOT:$<CONFIG:Debug>>:/Zi>")
|
||||
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/DEBUG>")
|
||||
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:REF>")
|
||||
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:ICF>")
|
||||
include(FindLua)
|
||||
message(STATUS "Looking for libz")
|
||||
find_package(ZLIB REQUIRED)
|
||||
@ -131,5 +139,7 @@ elseif (WIN32)
|
||||
${OPENSSL_LIBRARIES}
|
||||
commandline
|
||||
sioclient_tls
|
||||
sentry)
|
||||
sentry
|
||||
watchdog
|
||||
Dbghelp)
|
||||
endif ()
|
||||
|
8
include/watchdog/CMakeLists.txt
Normal file
8
include/watchdog/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(windows_dbg CXX ASM_MASM)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
add_library(windows_dbg STATIC watchdog.cpp watchdog.h x64Def.asm)
|
||||
set_source_files_properties(watchdog.cpp PROPERTIES COMPILE_FLAGS "/O2 /Ob2 /DNDEBUG")
|
||||
STRING(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
target_link_libraries(windows_dbg Dbghelp)
|
80
include/watchdog/stack_string.h
Normal file
80
include/watchdog/stack_string.h
Normal file
@ -0,0 +1,80 @@
|
||||
//
|
||||
// Created by Anonymous275 on 9/5/2021.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
namespace fst {
|
||||
template<size_t Cap>
|
||||
class stack_string {
|
||||
public:
|
||||
stack_string() noexcept {
|
||||
memset(Data, 0, Cap);
|
||||
}
|
||||
explicit stack_string(const char* Ptr) {
|
||||
size_t len = strlen(Ptr);
|
||||
Copy(Ptr, len);
|
||||
memset(Data + len, 0, Cap - len);
|
||||
}
|
||||
stack_string(const char* Ptr, size_t PSize) {
|
||||
Copy(Ptr, PSize);
|
||||
memset(Data + PSize, 0, Cap - PSize);
|
||||
}
|
||||
inline size_t capacity() noexcept {
|
||||
return Cap;
|
||||
}
|
||||
inline size_t size() noexcept {
|
||||
return Size;
|
||||
}
|
||||
inline size_t length() noexcept {
|
||||
return Size;
|
||||
}
|
||||
inline char* get() {
|
||||
return Data;
|
||||
}
|
||||
[[nodiscard]] inline const char* c_str() const noexcept {
|
||||
return Data;
|
||||
}
|
||||
char& operator[](size_t idx) {
|
||||
if (idx >= Size) {
|
||||
throw std::exception("stack_string out of boundaries operator[]");
|
||||
}
|
||||
return Data[idx];
|
||||
}
|
||||
inline void resize(size_t newSize) noexcept {
|
||||
Size = newSize;
|
||||
}
|
||||
inline void push_back(const char* Ptr) {
|
||||
Copy(Ptr, strlen(Ptr));
|
||||
}
|
||||
inline void push_back(const char* Ptr, size_t Count) {
|
||||
Copy(Ptr, Count);
|
||||
}
|
||||
inline void push_back(char Ptr) {
|
||||
Copy(&Ptr, 1);
|
||||
}
|
||||
friend std::ostream& operator<<(std::ostream& os, const stack_string& obj) {
|
||||
os << obj.Data;
|
||||
return os;
|
||||
}
|
||||
inline stack_string& operator+=(const char* Ptr) {
|
||||
push_back(Ptr);
|
||||
return *this;
|
||||
}
|
||||
inline stack_string& operator+=(char Ptr) {
|
||||
push_back(Ptr);
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
inline void Copy(const char* Ptr, size_t PSize) {
|
||||
if((PSize + Size) <= Cap) {
|
||||
memcpy(&Data[Size], Ptr, PSize);
|
||||
Size += PSize;
|
||||
} else throw std::exception("stack_string out of boundaries copy");
|
||||
}
|
||||
char Data[Cap]{};
|
||||
size_t Size{0};
|
||||
};
|
||||
}
|
281
include/watchdog/watchdog.cpp
Normal file
281
include/watchdog/watchdog.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
//
|
||||
// Created by Anonymous275 on 9/9/2021.
|
||||
//
|
||||
|
||||
#include <windows.h>
|
||||
#include <imagehlp.h>
|
||||
#include <strsafe.h>
|
||||
#include <cstdint>
|
||||
#include "stack_string.h"
|
||||
|
||||
struct function_info {
|
||||
void* func_address;
|
||||
uint32_t thread_id;
|
||||
bool enter;
|
||||
};
|
||||
|
||||
fst::stack_string<1024> crash_file;
|
||||
|
||||
template <typename I>
|
||||
fst::stack_string<(sizeof(I)<<1)+1> HexString(I w) {
|
||||
static const char* digits = "0123456789ABCDEF";
|
||||
const size_t hex_len = sizeof(I)<<1;
|
||||
fst::stack_string<hex_len+1> rc;
|
||||
rc.resize(hex_len+1);
|
||||
memset(rc.get(), '0', hex_len);
|
||||
memset(rc.get() + hex_len, 0, 1);
|
||||
for (size_t i=0, j=(hex_len-1)*4 ; i<hex_len; ++i,j-=4)
|
||||
rc[i] = digits[(w>>j) & 0x0f];
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<class T_>
|
||||
class heap_array {
|
||||
public:
|
||||
heap_array() noexcept {
|
||||
Data = (T_*)(GlobalAlloc(GPTR, Cap * sizeof(T_)));
|
||||
init = true;
|
||||
}
|
||||
explicit heap_array(size_t Cap_) noexcept {
|
||||
Cap = Cap_;
|
||||
Data = (T_*)(GlobalAlloc(GPTR, Cap * sizeof(T_)));
|
||||
init = true;
|
||||
}
|
||||
~heap_array() {
|
||||
free(Data);
|
||||
}
|
||||
inline T_* get() noexcept {
|
||||
return Data;
|
||||
}
|
||||
inline const T_* cget() noexcept {
|
||||
return Data;
|
||||
}
|
||||
inline void insert(const T_& T) {
|
||||
if(!init)return;
|
||||
if(Size >= Cap) {
|
||||
Grow();
|
||||
}
|
||||
Data[Size++] = T;
|
||||
}
|
||||
inline void string_insert(const T_* T, size_t len = 0) {
|
||||
if(len == 0)len = strlen(T);
|
||||
if(Size+len >= Cap) {
|
||||
Grow(len);
|
||||
}
|
||||
memcpy(&Data[Size], T, len);
|
||||
Size += len;
|
||||
}
|
||||
inline T_ at(size_t idx) {
|
||||
return Data[idx];
|
||||
}
|
||||
inline size_t size() const noexcept {
|
||||
return Size;
|
||||
}
|
||||
const T_& operator[](size_t idx) {
|
||||
if (idx >= Size) {
|
||||
throw std::exception("out of boundaries operator[]");
|
||||
}
|
||||
return Data[idx];
|
||||
}
|
||||
private:
|
||||
inline void Grow(size_t add = 0) {
|
||||
Cap = (Cap*2) + add;
|
||||
auto* NewData = (T_*)(GlobalAlloc(GPTR, Cap * sizeof(T_)));
|
||||
for(size_t C = 0; C < Size; C++) {
|
||||
NewData[C] = Data[C];
|
||||
}
|
||||
GlobalFree(Data);
|
||||
Data = NewData;
|
||||
}
|
||||
size_t Size{0}, Cap{5};
|
||||
bool init{false};
|
||||
T_* Data;
|
||||
};
|
||||
|
||||
heap_array<function_info>* watch_data;
|
||||
|
||||
struct watchdog_mutex {
|
||||
static void Create() noexcept {
|
||||
hMutex = CreateMutex(nullptr, FALSE, nullptr);
|
||||
}
|
||||
static void Lock() {
|
||||
WaitForSingleObject(hMutex, INFINITE);
|
||||
}
|
||||
static void Unlock() {
|
||||
ReleaseMutex(hMutex);
|
||||
}
|
||||
struct [[nodiscard]] ScopedLock {
|
||||
ScopedLock() {
|
||||
if(hMutex)
|
||||
watchdog_mutex::Lock();
|
||||
}
|
||||
~ScopedLock() {
|
||||
if(hMutex)
|
||||
watchdog_mutex::Unlock();
|
||||
}
|
||||
};
|
||||
private:
|
||||
static HANDLE hMutex;
|
||||
};
|
||||
HANDLE watchdog_mutex::hMutex{nullptr};
|
||||
std::atomic<bool> Init{false}, Sym;
|
||||
std::atomic<int64_t> Offset{0};
|
||||
|
||||
void watchdog_setOffset(int64_t Off) {
|
||||
Offset.store(Off);
|
||||
}
|
||||
|
||||
void notify(const char* msg) {
|
||||
HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (stdOut != nullptr && stdOut != INVALID_HANDLE_VALUE) {
|
||||
DWORD written = 0;
|
||||
WriteConsoleA(stdOut, "[WATCHDOG] ", 11, &written, nullptr);
|
||||
WriteConsoleA(stdOut, msg, DWORD(strlen(msg)), &written, nullptr);
|
||||
WriteConsoleA(stdOut, "\n", 1, &written, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
fst::stack_string<MAX_SYM_NAME> FindFunction(void* Address) {
|
||||
if(!Sym.load()) {
|
||||
fst::stack_string<MAX_SYM_NAME> undName;
|
||||
return undName;
|
||||
}
|
||||
static HANDLE process = GetCurrentProcess();
|
||||
DWORD64 symDisplacement = 0;
|
||||
fst::stack_string<MAX_SYM_NAME> undName;
|
||||
TCHAR buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
|
||||
memset(&buffer,0, sizeof(buffer));
|
||||
auto pSymbolInfo = (PSYMBOL_INFO)buffer;
|
||||
pSymbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbolInfo->MaxNameLen = MAX_SYM_NAME;
|
||||
if (SymFromAddr(process, DWORD64(Address) + Offset, &symDisplacement, pSymbolInfo)) {
|
||||
undName.push_back(pSymbolInfo->Name);
|
||||
}
|
||||
return undName;
|
||||
}
|
||||
|
||||
|
||||
fst::stack_string<512> getCrashInfo(void* Address){
|
||||
if(!Sym.load()){
|
||||
fst::stack_string<512> Value;
|
||||
Value.push_back("unknown", 7);
|
||||
return Value;
|
||||
}
|
||||
DWORD pdwDisplacement = 0;
|
||||
IMAGEHLP_LINE64 line{sizeof(IMAGEHLP_LINE64)};
|
||||
SymGetLineFromAddr64(GetCurrentProcess(), DWORD64(Address) + Offset, &pdwDisplacement, &line);
|
||||
char* Name = nullptr;
|
||||
if(line.FileName) {
|
||||
Name = strrchr(line.FileName, '\\');
|
||||
}
|
||||
fst::stack_string<512> Value;
|
||||
if(Name)Value.push_back(Name+1);
|
||||
else Value.push_back("unknown", 7);
|
||||
char buffer[20];
|
||||
auto n = sprintf(buffer, ":%lu", line.LineNumber);
|
||||
Value.push_back(buffer, n);
|
||||
return Value;
|
||||
}
|
||||
const char* getFunctionDetails(void* Address) {
|
||||
return FindFunction(Address).c_str();
|
||||
}
|
||||
const char* getCrashLocation(void* Address) {
|
||||
return getCrashInfo(Address).c_str();
|
||||
}
|
||||
|
||||
void InitSym(const char* PDBLocation) {
|
||||
SymInitialize(GetCurrentProcess(), PDBLocation, TRUE);
|
||||
Sym.store(true);
|
||||
}
|
||||
|
||||
void write_report(const char* report, size_t size) {
|
||||
HANDLE hFile = CreateFile(crash_file.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
notify("Failed to open crash file for writing!");
|
||||
return;
|
||||
}
|
||||
DWORD dwBytesWritten = 0;
|
||||
auto Flag = WriteFile(hFile, report, DWORD(size), &dwBytesWritten, nullptr);
|
||||
if (Flag == FALSE) {
|
||||
notify("Failed to write to crash file!");
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
void generate_crash_report(uint32_t Code, void* Address) {
|
||||
watchdog_mutex::ScopedLock guard;
|
||||
notify("generating crash report, please wait");
|
||||
Init.store(false);
|
||||
heap_array<char> Report(watch_data->size() * sizeof(function_info));
|
||||
Report.string_insert("crash code ");
|
||||
Report.string_insert(HexString(Code).c_str());
|
||||
Report.string_insert(" at ");
|
||||
Report.string_insert(HexString(size_t(Address) + Offset).c_str());
|
||||
Report.string_insert("\n");
|
||||
if(Address) {
|
||||
Report.string_insert("origin and line number -> ");
|
||||
Report.string_insert(getCrashInfo(Address).c_str());
|
||||
Report.string_insert("\n");
|
||||
}
|
||||
Report.string_insert("Call history: \n");
|
||||
char buff[20];
|
||||
for(size_t C = 0; C < watch_data->size(); C++){
|
||||
auto entry = watch_data->at(C);
|
||||
auto Name = FindFunction(entry.func_address);
|
||||
if(entry.enter){
|
||||
Report.string_insert("[Entry] ");
|
||||
}
|
||||
else {
|
||||
Report.string_insert("[Exit ] ");
|
||||
}
|
||||
auto n = sprintf(buff, "(%d) ", entry.thread_id);
|
||||
Report.string_insert(buff, n);
|
||||
if(Name.size() > 0){
|
||||
Report.string_insert(Name.c_str(), Name.size());
|
||||
Report.string_insert(" | ");
|
||||
auto location = getCrashInfo(entry.func_address);
|
||||
Report.string_insert(location.c_str(), location.size());
|
||||
}
|
||||
else {
|
||||
Report.string_insert(HexString(size_t(entry.func_address) + Offset).c_str());
|
||||
}
|
||||
Report.string_insert("\n");
|
||||
}
|
||||
write_report(Report.cget(), Report.size());
|
||||
notify("crash report generated");
|
||||
Init.store(true);
|
||||
}
|
||||
|
||||
LONG WINAPI CrashHandler(EXCEPTION_POINTERS* p) {
|
||||
Init.store(false);
|
||||
notify("CAUGHT EXCEPTION!");
|
||||
generate_crash_report(p->ExceptionRecord->ExceptionCode, p->ExceptionRecord->ExceptionAddress);
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
void watchdog_init(const char* crashFile, const char* SpecificPDBLocation, bool Symbols) {
|
||||
if(Symbols)SymInitialize(GetCurrentProcess(), SpecificPDBLocation, TRUE);
|
||||
Sym.store(Symbols);
|
||||
SetUnhandledExceptionFilter(CrashHandler);
|
||||
watch_data = new heap_array<function_info>();
|
||||
watchdog_mutex::Create();
|
||||
crash_file.push_back(crashFile);
|
||||
notify("initialized!");
|
||||
Init.store(true);
|
||||
}
|
||||
|
||||
inline void AddEntry(void* func_address, uint32_t thread_id, bool entry) {
|
||||
watchdog_mutex::ScopedLock guard;
|
||||
if(Init.load()) {
|
||||
watch_data->insert({func_address, thread_id, entry});
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void FuncEntry(void* func) {
|
||||
AddEntry(func, GetCurrentThreadId(), true);
|
||||
}
|
||||
void FuncExit(void* func) {
|
||||
AddEntry(func, GetCurrentThreadId(), false);
|
||||
}
|
||||
}
|
12
include/watchdog/watchdog.h
Normal file
12
include/watchdog/watchdog.h
Normal file
@ -0,0 +1,12 @@
|
||||
//
|
||||
// Created by Anonymous275 on 9/9/2021.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
extern void watchdog_init(const char* crashFile, const char* SpecificPDBLocation, bool Symbols = true);
|
||||
extern void generate_crash_report(uint32_t Code, void* Address);
|
||||
const char* getFunctionDetails(void* Address);
|
||||
extern void watchdog_setOffset(int64_t Off);
|
||||
const char* getCrashLocation(void* Address);
|
||||
void InitSym(const char* PDBLocation);
|
85
include/watchdog/x64Def.asm
Normal file
85
include/watchdog/x64Def.asm
Normal file
@ -0,0 +1,85 @@
|
||||
;//
|
||||
;// Created by Anonymous275 on 9/9/2021.
|
||||
;//
|
||||
;External C functions used by _penter and _pexit
|
||||
extern FuncEntry:Proc
|
||||
extern FuncExit:Proc
|
||||
|
||||
.code
|
||||
|
||||
_penter proc
|
||||
|
||||
; Store the volatile registers
|
||||
push r11
|
||||
push r10
|
||||
push r9
|
||||
push r8
|
||||
push rax
|
||||
push rdx
|
||||
push rcx
|
||||
|
||||
; reserve space for 4 registers [ rcx,rdx,r8 and r9 ] 32 bytes
|
||||
sub rsp,20h
|
||||
|
||||
; Get the return address of the function
|
||||
mov rcx,rsp
|
||||
mov rcx,qword ptr[rcx+58h]
|
||||
sub rcx,5
|
||||
|
||||
;call the function to get the name of the callee and caller
|
||||
call FuncEntry
|
||||
|
||||
;Release the space reserved for the registersk by adding 32 bytes
|
||||
add rsp,20h
|
||||
|
||||
;Restore the registers back by poping out
|
||||
pop rcx
|
||||
pop rdx
|
||||
pop rax
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
|
||||
;return
|
||||
ret
|
||||
|
||||
_penter endp
|
||||
|
||||
_pexit proc
|
||||
|
||||
; Store the volatile registers
|
||||
push r11
|
||||
push r10
|
||||
push r9
|
||||
push r8
|
||||
push rax
|
||||
push rdx
|
||||
push rcx
|
||||
|
||||
; reserve space for 4 registers [ rcx,rdx,r8 and r9 ] 32 bytes
|
||||
sub rsp,20h
|
||||
|
||||
; Get the return address of the function
|
||||
mov rcx,rsp
|
||||
mov rcx,qword ptr[rcx+58h]
|
||||
|
||||
call FuncExit
|
||||
|
||||
;Release the space reserved for the registersk by adding 32 bytes
|
||||
add rsp,20h
|
||||
|
||||
;Restore the registers back by poping out
|
||||
pop rcx
|
||||
pop rdx
|
||||
pop rax
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
|
||||
;return
|
||||
ret
|
||||
|
||||
_pexit endp
|
||||
end
|
80
src/main.cpp
80
src/main.cpp
@ -11,7 +11,7 @@
|
||||
#include "TPPSMonitor.h"
|
||||
#include "TResourceManager.h"
|
||||
#include "TServer.h"
|
||||
|
||||
#include "../include/watchdog/watchdog.h"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
@ -19,47 +19,51 @@
|
||||
// global, yes, this is ugly, no, it cant be done another way
|
||||
TSentry Sentry {};
|
||||
|
||||
int main(int argc, char** argv) try {
|
||||
setlocale(LC_ALL, "C");
|
||||
int main(int argc, char** argv) {
|
||||
watchdog_init("watchdog_crash.log", "C:\\Users\\Anonymous\\Documents\\GitHub\\BeamMP-Server\\RelWithDebInfo");
|
||||
try {
|
||||
setlocale(LC_ALL, "C");
|
||||
|
||||
SetupSignalHandlers();
|
||||
SetupSignalHandlers();
|
||||
|
||||
bool Shutdown = false;
|
||||
Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; });
|
||||
bool Shutdown = false;
|
||||
Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; });
|
||||
|
||||
TServer Server(argc, argv);
|
||||
TConfig Config;
|
||||
TServer Server(argc, argv);
|
||||
TConfig Config;
|
||||
|
||||
if (Config.Failed()) {
|
||||
info("Closing in 10 seconds");
|
||||
// loop to make it possible to ctrl+c instead
|
||||
for (size_t i = 0; i < 20; ++i) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
if (Config.Failed()) {
|
||||
info("Closing in 10 seconds");
|
||||
// loop to make it possible to ctrl+c instead
|
||||
for (size_t i = 0; i < 20; ++i) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
|
||||
RegisterThread("Main");
|
||||
|
||||
trace("Running in debug mode on a debug build");
|
||||
|
||||
Sentry.SetupUser();
|
||||
Sentry.PrintWelcome();
|
||||
TResourceManager ResourceManager;
|
||||
TPPSMonitor PPSMonitor(Server);
|
||||
THeartbeatThread Heartbeat(ResourceManager, Server);
|
||||
TNetwork Network(Server, PPSMonitor, ResourceManager);
|
||||
TLuaEngine LuaEngine(Server, Network);
|
||||
PPSMonitor.SetNetwork(Network);
|
||||
Application::Console().InitializeLuaConsole(LuaEngine);
|
||||
Application::CheckForUpdates();
|
||||
|
||||
// TODO: replace
|
||||
while (!Shutdown) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
info("Shutdown.");
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
error(e.what());
|
||||
Sentry.LogException(e, _file_basename, _line);
|
||||
}
|
||||
|
||||
RegisterThread("Main");
|
||||
|
||||
trace("Running in debug mode on a debug build");
|
||||
|
||||
Sentry.SetupUser();
|
||||
Sentry.PrintWelcome();
|
||||
TResourceManager ResourceManager;
|
||||
TPPSMonitor PPSMonitor(Server);
|
||||
THeartbeatThread Heartbeat(ResourceManager, Server);
|
||||
TNetwork Network(Server, PPSMonitor, ResourceManager);
|
||||
TLuaEngine LuaEngine(Server, Network);
|
||||
PPSMonitor.SetNetwork(Network);
|
||||
Application::Console().InitializeLuaConsole(LuaEngine);
|
||||
Application::CheckForUpdates();
|
||||
|
||||
// TODO: replace
|
||||
while (!Shutdown) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
info("Shutdown.");
|
||||
} catch (const std::exception& e) {
|
||||
error(e.what());
|
||||
Sentry.LogException(e, _file_basename, _line);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user