mirror of
https://github.com/ddnet/ddnet.git
synced 2024-10-21 00:08:19 +00:00
ba5a974353
The client/server jobpools were previously only using a fixed number of 2 threads. Now the pools use `2 * hardware-concurrency + 2` threads, which should provide better performance overall, as we expect threads to often wait on I/O.
208 lines
5.9 KiB
C++
208 lines
5.9 KiB
C++
|
|
#define _WIN32_WINNT 0x0501
|
|
|
|
#include <base/logger.h>
|
|
#include <base/system.h>
|
|
|
|
#include <engine/console.h>
|
|
#include <engine/engine.h>
|
|
#include <engine/map.h>
|
|
#include <engine/server.h>
|
|
#include <engine/storage.h>
|
|
|
|
#include <engine/server/antibot.h>
|
|
#include <engine/server/databases/connection.h>
|
|
#include <engine/server/server.h>
|
|
#include <engine/server/server_logger.h>
|
|
|
|
#include <engine/shared/assertion_logger.h>
|
|
#include <engine/shared/config.h>
|
|
|
|
#include <game/version.h>
|
|
|
|
#include <vector>
|
|
|
|
#if defined(CONF_FAMILY_WINDOWS)
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include <csignal>
|
|
|
|
volatile sig_atomic_t InterruptSignaled = 0;
|
|
|
|
bool IsInterrupted()
|
|
{
|
|
return InterruptSignaled;
|
|
}
|
|
|
|
void HandleSigIntTerm(int Param)
|
|
{
|
|
InterruptSignaled = 1;
|
|
|
|
// Exit the next time a signal is received
|
|
signal(SIGINT, SIG_DFL);
|
|
signal(SIGTERM, SIG_DFL);
|
|
}
|
|
|
|
int main(int argc, const char **argv)
|
|
{
|
|
CCmdlineFix CmdlineFix(&argc, &argv);
|
|
bool Silent = false;
|
|
|
|
for(int i = 1; i < argc; i++)
|
|
{
|
|
if(str_comp("-s", argv[i]) == 0 || str_comp("--silent", argv[i]) == 0)
|
|
{
|
|
Silent = true;
|
|
#if defined(CONF_FAMILY_WINDOWS)
|
|
ShowWindow(GetConsoleWindow(), SW_HIDE);
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if defined(CONF_FAMILY_WINDOWS)
|
|
CWindowsComLifecycle WindowsComLifecycle(false);
|
|
#endif
|
|
|
|
std::vector<std::shared_ptr<ILogger>> vpLoggers;
|
|
std::shared_ptr<ILogger> pStdoutLogger;
|
|
#if defined(CONF_PLATFORM_ANDROID)
|
|
pStdoutLogger = std::shared_ptr<ILogger>(log_logger_android());
|
|
#else
|
|
if(!Silent)
|
|
{
|
|
pStdoutLogger = std::shared_ptr<ILogger>(log_logger_stdout());
|
|
}
|
|
#endif
|
|
if(pStdoutLogger)
|
|
{
|
|
vpLoggers.push_back(pStdoutLogger);
|
|
}
|
|
std::shared_ptr<CFutureLogger> pFutureFileLogger = std::make_shared<CFutureLogger>();
|
|
vpLoggers.push_back(pFutureFileLogger);
|
|
std::shared_ptr<CFutureLogger> pFutureConsoleLogger = std::make_shared<CFutureLogger>();
|
|
vpLoggers.push_back(pFutureConsoleLogger);
|
|
std::shared_ptr<CFutureLogger> pFutureAssertionLogger = std::make_shared<CFutureLogger>();
|
|
vpLoggers.push_back(pFutureAssertionLogger);
|
|
log_set_global_logger(log_logger_collection(std::move(vpLoggers)).release());
|
|
|
|
if(secure_random_init() != 0)
|
|
{
|
|
dbg_msg("secure", "could not initialize secure RNG");
|
|
return -1;
|
|
}
|
|
if(MysqlInit() != 0)
|
|
{
|
|
dbg_msg("mysql", "failed to initialize MySQL library");
|
|
return -1;
|
|
}
|
|
|
|
signal(SIGINT, HandleSigIntTerm);
|
|
signal(SIGTERM, HandleSigIntTerm);
|
|
|
|
#if defined(CONF_EXCEPTION_HANDLING)
|
|
init_exception_handler();
|
|
#endif
|
|
|
|
CServer *pServer = CreateServer();
|
|
pServer->SetLoggers(pFutureFileLogger, std::move(pStdoutLogger));
|
|
|
|
IKernel *pKernel = IKernel::Create();
|
|
|
|
// create the components
|
|
IEngine *pEngine = CreateEngine(GAME_NAME, pFutureConsoleLogger, 2 * std::thread::hardware_concurrency() + 2);
|
|
IEngineMap *pEngineMap = CreateEngineMap();
|
|
IGameServer *pGameServer = CreateGameServer();
|
|
IConsole *pConsole = CreateConsole(CFGFLAG_SERVER | CFGFLAG_ECON).release();
|
|
IStorage *pStorage = CreateStorage(IStorage::STORAGETYPE_SERVER, argc, argv);
|
|
IConfigManager *pConfigManager = CreateConfigManager();
|
|
IEngineAntibot *pEngineAntibot = CreateEngineAntibot();
|
|
|
|
pFutureAssertionLogger->Set(CreateAssertionLogger(pStorage, GAME_NAME));
|
|
#if defined(CONF_EXCEPTION_HANDLING)
|
|
char aBuf[IO_MAX_PATH_LENGTH];
|
|
char aBufName[IO_MAX_PATH_LENGTH];
|
|
char aDate[64];
|
|
str_timestamp(aDate, sizeof(aDate));
|
|
str_format(aBufName, sizeof(aBufName), "dumps/" GAME_NAME "-Server_%s_crash_log_%s_%d_%s.RTP", CONF_PLATFORM_STRING, aDate, pid(), GIT_SHORTREV_HASH != nullptr ? GIT_SHORTREV_HASH : "");
|
|
pStorage->GetCompletePath(IStorage::TYPE_SAVE, aBufName, aBuf, sizeof(aBuf));
|
|
set_exception_handler_log_file(aBuf);
|
|
#endif
|
|
|
|
{
|
|
bool RegisterFail = false;
|
|
|
|
RegisterFail = RegisterFail || !pKernel->RegisterInterface(pServer);
|
|
RegisterFail = RegisterFail || !pKernel->RegisterInterface(pEngine);
|
|
RegisterFail = RegisterFail || !pKernel->RegisterInterface(pEngineMap); // register as both
|
|
RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IMap *>(pEngineMap), false);
|
|
RegisterFail = RegisterFail || !pKernel->RegisterInterface(pGameServer);
|
|
RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConsole);
|
|
RegisterFail = RegisterFail || !pKernel->RegisterInterface(pStorage);
|
|
RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConfigManager);
|
|
RegisterFail = RegisterFail || !pKernel->RegisterInterface(pEngineAntibot);
|
|
RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IAntibot *>(pEngineAntibot), false);
|
|
|
|
if(RegisterFail)
|
|
{
|
|
delete pKernel;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
pEngine->Init();
|
|
pConfigManager->Init();
|
|
pConsole->Init();
|
|
|
|
// register all console commands
|
|
pServer->RegisterCommands();
|
|
|
|
// execute autoexec file
|
|
if(pStorage->FileExists(AUTOEXEC_SERVER_FILE, IStorage::TYPE_ALL))
|
|
{
|
|
pConsole->ExecuteFile(AUTOEXEC_SERVER_FILE);
|
|
}
|
|
else // fallback
|
|
{
|
|
pConsole->ExecuteFile(AUTOEXEC_FILE);
|
|
}
|
|
|
|
// parse the command line arguments
|
|
if(argc > 1)
|
|
pConsole->ParseArguments(argc - 1, &argv[1]);
|
|
|
|
pConsole->Register("sv_test_cmds", "", CFGFLAG_SERVER, CServer::ConTestingCommands, pConsole, "Turns testing commands aka cheats on/off (setting only works in initial config)");
|
|
pConsole->Register("sv_rescue", "", CFGFLAG_SERVER, CServer::ConRescue, pConsole, "Allow /rescue command so players can teleport themselves out of freeze (setting only works in initial config)");
|
|
|
|
const int Mode = g_Config.m_Logappend ? IOFLAG_APPEND : IOFLAG_WRITE;
|
|
if(g_Config.m_Logfile[0])
|
|
{
|
|
IOHANDLE Logfile = pStorage->OpenFile(g_Config.m_Logfile, Mode, IStorage::TYPE_SAVE_OR_ABSOLUTE);
|
|
if(Logfile)
|
|
{
|
|
pFutureFileLogger->Set(log_logger_file(Logfile));
|
|
}
|
|
else
|
|
{
|
|
dbg_msg("server", "failed to open '%s' for logging", g_Config.m_Logfile);
|
|
}
|
|
}
|
|
auto pServerLogger = std::make_shared<CServerLogger>(pServer);
|
|
pEngine->SetAdditionalLogger(pServerLogger);
|
|
|
|
// run the server
|
|
dbg_msg("server", "starting...");
|
|
int Ret = pServer->Run();
|
|
|
|
pServerLogger->OnServerDeletion();
|
|
// free
|
|
delete pKernel;
|
|
|
|
MysqlUninit();
|
|
secure_random_uninit();
|
|
|
|
return Ret;
|
|
}
|