From 64e53bace3d299cea30000aae5b0bbee52a9099a Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Mon, 28 Sep 2026 11:35:51 -0500 Subject: [PATCH] fix(master): a server that fails to start doesn't leave a second master running When execl failed in the forked child (seen when WorldServer was being relinked as a property world was started), the child carried on as a copy of the master: it logged "WorldServer PID is 0" and kept running, and the player waiting for that world stayed stuck. The child now reports the error and exits. Co-Authored-By: Claude Opus 5.5 --- dMasterServer/Start.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/dMasterServer/Start.cpp b/dMasterServer/Start.cpp index b9655bbff..024abb005 100644 --- a/dMasterServer/Start.cpp +++ b/dMasterServer/Start.cpp @@ -32,6 +32,7 @@ namespace { }; } #else +#include #include #endif @@ -65,6 +66,9 @@ uint32_t StartChatServer() { } else if (chat_pid == 0) { // We are the child process execl(chat_path.string().c_str(), chat_path.string().c_str(), nullptr); + // exec failed (e.g. the binary is being rebuilt): the child must not carry on as a second master + perror("exec"); + _exit(127); } #endif LOG("ChatServer PID is %d", chat_pid); @@ -101,6 +105,9 @@ uint32_t StartAuthServer() { } else if (auth_pid == 0) { // We are the child process execl(auth_path.string().c_str(), auth_path.string().c_str(), nullptr); + // exec failed (e.g. the binary is being rebuilt): the child must not carry on as a second master + perror("exec"); + _exit(127); } #endif LOG("AuthServer PID is %d", auth_pid); @@ -137,6 +144,9 @@ uint32_t StartDashboardServer() { } else if (web_pid == 0) { // We are the child process execl(web_path.string().c_str(), web_path.string().c_str(), nullptr); + // exec failed (e.g. the binary is being rebuilt): the child must not carry on as a second master + perror("exec"); + _exit(127); } #endif LOG("DashboardServer PID is %d", web_pid); @@ -173,6 +183,9 @@ uint32_t StartUgcServer() { } else if (ugc_pid == 0) { // We are the child process execl(ugc_path.string().c_str(), ugc_path.string().c_str(), nullptr); + // exec failed (e.g. the binary is being rebuilt): the child must not carry on as a second master + perror("exec"); + _exit(127); } #endif LOG("UgcServer PID is %d", ugc_pid); @@ -214,6 +227,9 @@ uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInsta "-instance", std::to_string(lastInstanceID).c_str(), "-maxclients", std::to_string(maxPlayers).c_str(), "-clone", std::to_string(cloneID).c_str(), nullptr); + // exec failed (e.g. the binary is being rebuilt): the child must not carry on as a second master + perror("exec"); + _exit(127); } #endif LOG("WorldServer PID is %d", world_pid);