feat: Replace calls to system function in server startups (#1691)

* replace linux calls

* windows api

* log child PIDs in parent process

* fix typo for windows

* functions now return the process ID

* use wchar_t for windows APIs

* Update Start.cpp

Try to fix MacOS issues

* Conditionally include unistd.h

* remove sudo config option and add error message for linux

* fix windows .exe extension

* REALLY fix windows

* try replacing c_str() with data()

* really REALLY fix Windows

* Update dNet/dServer.cpp

Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>

* Update dServer.cpp
This commit is contained in:
jadebenn
2025-01-01 17:41:21 -06:00
committed by GitHub
parent 5ccd15a7d8
commit 71baa5ce90
7 changed files with 157 additions and 81 deletions

View File

@@ -4,68 +4,146 @@
#include "Game.h"
#include "BinaryPathFinder.h"
void StartChatServer() {
#ifdef _WIN32
#include <windows.h>
#include <handleapi.h>
#include <processthreadsapi.h>
namespace {
const auto startup = STARTUPINFOW{
.cb = sizeof(STARTUPINFOW),
.lpReserved = nullptr,
.lpDesktop = nullptr,
.lpTitle = nullptr,
.dwX = 0,
.dwY = 0,
.dwXSize = 0,
.dwYSize = 0,
.dwXCountChars = 0,
.dwYCountChars = 0,
.dwFillAttribute = 0,
.dwFlags = 0,
.wShowWindow = 0,
.cbReserved2 = 0,
.lpReserved2 = nullptr,
.hStdInput = INVALID_HANDLE_VALUE,
.hStdOutput = INVALID_HANDLE_VALUE,
.hStdError = INVALID_HANDLE_VALUE,
};
}
#else
#include <unistd.h>
#endif
uint32_t StartChatServer() {
if (Game::ShouldShutdown()) {
LOG("Currently shutting down. Chat will not be restarted.");
return;
return 0;
}
auto chat_path = BinaryPathFinder::GetBinaryDir() / "ChatServer";
#ifdef _WIN32
chat_path.replace_extension(".exe");
auto chat_startup = startup;
auto chat_info = PROCESS_INFORMATION{};
if (!CreateProcessW(chat_path.wstring().data(), chat_path.wstring().data(),
nullptr, nullptr, false, 0, nullptr, nullptr,
&chat_startup, &chat_info))
{
LOG("Failed to launch ChatServer");
return 0;
}
// get pid and close unused handles
auto chat_pid = chat_info.dwProcessId;
CloseHandle(chat_info.hProcess);
CloseHandle(chat_info.hThread);
#else // *nix systems
const auto chat_pid = fork();
if (chat_pid < 0) {
LOG("Failed to launch ChatServer");
return 0;
} else if (chat_pid == 0) {
// We are the child process
execl(chat_path.string().c_str(), chat_path.string().c_str(), nullptr);
}
#ifdef __APPLE__
//macOS doesn't need sudo to run on ports < 1024
auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
#elif _WIN32
auto result = system(("start /B " + (BinaryPathFinder::GetBinaryDir() / "ChatServer.exe").string()).c_str());
#else
if (std::atoi(Game::config->GetValue("use_sudo_chat").c_str())) {
auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
} else {
auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
}
#endif
LOG("ChatServer PID is %d", chat_pid);
return chat_pid;
}
void StartAuthServer() {
uint32_t StartAuthServer() {
if (Game::ShouldShutdown()) {
LOG("Currently shutting down. Auth will not be restarted.");
return;
return 0;
}
#ifdef __APPLE__
auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
#elif _WIN32
auto result = system(("start /B " + (BinaryPathFinder::GetBinaryDir() / "AuthServer.exe").string()).c_str());
#else
if (std::atoi(Game::config->GetValue("use_sudo_auth").c_str())) {
auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
} else {
auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
}
#endif
}
void StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID) {
auto auth_path = BinaryPathFinder::GetBinaryDir() / "AuthServer";
#ifdef _WIN32
std::string cmd = "start /B " + (BinaryPathFinder::GetBinaryDir() / "WorldServer.exe").string() + " -zone ";
#else
std::string cmd;
if (std::atoi(Game::config->GetValue("use_sudo_world").c_str())) {
cmd = "sudo " + (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
} else {
cmd = (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
auth_path.replace_extension(".exe");
auto auth_startup = startup;
auto auth_info = PROCESS_INFORMATION{};
if (!CreateProcessW(auth_path.wstring().data(), auth_path.wstring().data(),
nullptr, nullptr, false, 0, nullptr, nullptr,
&auth_startup, &auth_info))
{
LOG("Failed to launch AuthServer");
return 0;
}
// get pid and close unused handles
auto auth_pid = auth_info.dwProcessId;
CloseHandle(auth_info.hProcess);
CloseHandle(auth_info.hThread);
#else // *nix systems
const auto auth_pid = fork();
if (auth_pid < 0) {
LOG("Failed to launch AuthServer");
return 0;
} else if (auth_pid == 0) {
// We are the child process
execl(auth_path.string().c_str(), auth_path.string().c_str(), nullptr);
}
#endif
cmd.append(std::to_string(mapID));
cmd.append(" -port ");
cmd.append(std::to_string(port));
cmd.append(" -instance ");
cmd.append(std::to_string(lastInstanceID));
cmd.append(" -maxclients ");
cmd.append(std::to_string(maxPlayers));
cmd.append(" -clone ");
cmd.append(std::to_string(cloneID));
#ifndef _WIN32
cmd.append("&"); //Sends our next process to the background on Linux
#endif
auto ret = system(cmd.c_str());
LOG("AuthServer PID is %d", auth_pid);
return auth_pid;
}
uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID) {
auto world_path = BinaryPathFinder::GetBinaryDir() / "WorldServer";
#ifdef _WIN32
world_path.replace_extension(".exe");
auto cmd = world_path.wstring() + L" -zone " + std::to_wstring(mapID) + L" -port " + std::to_wstring(port) +
L" -instance " + std::to_wstring(lastInstanceID) + L" -maxclients " + std::to_wstring(maxPlayers) +
L" -clone " + std::to_wstring(cloneID);
auto world_startup = startup;
auto world_info = PROCESS_INFORMATION{};
if (!CreateProcessW(world_path.wstring().data(), cmd.data(),
nullptr, nullptr, false, 0, nullptr, nullptr,
&world_startup, &world_info))
{
LOG("Failed to launch WorldServer");
return 0;
}
// get pid and close unused handles
auto world_pid = world_info.dwProcessId;
CloseHandle(world_info.hProcess);
CloseHandle(world_info.hThread);
#else
const auto world_pid = fork();
if (world_pid < 0) {
LOG("Failed to launch WorldServer");
return 0;
} else if (world_pid == 0) {
// We are the child process
execl(world_path.string().c_str(), world_path.string().c_str(),
"-zone", std::to_string(mapID).c_str(),
"-port", std::to_string(port).c_str(),
"-instance", std::to_string(lastInstanceID).c_str(),
"-maxclients", std::to_string(maxPlayers).c_str(),
"-clone", std::to_string(cloneID).c_str(), nullptr);
}
#endif
LOG("WorldServer PID is %d", world_pid);
return world_pid;
}

View File

@@ -1,6 +1,6 @@
#pragma once
#include "dCommonVars.h"
void StartAuthServer();
void StartChatServer();
void StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID);
uint32_t StartAuthServer();
uint32_t StartChatServer();
uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID);