From 7daf51f2da79ff8ec2a2b4d3c9ce9b98b2b2dee8 Mon Sep 17 00:00:00 2001 From: server Date: Tue, 14 Apr 2026 06:04:12 +0200 Subject: [PATCH] runtime: improve startup observability --- src/db/Main.cpp | 40 ++++++++++++++++++++++++- src/game/main.cpp | 61 ++++++++++++++++++++++++++++++++++++++- src/libthecore/socket.cpp | 27 +++++++++++++++++ 3 files changed, 126 insertions(+), 2 deletions(-) diff --git a/src/db/Main.cpp b/src/db/Main.cpp index cd71952..4801d9a 100644 --- a/src/db/Main.cpp +++ b/src/db/Main.cpp @@ -45,6 +45,43 @@ extern const char * _malloc_options; extern void WriteVersion(); +namespace +{ +const char* BoolState(bool value) +{ + return value ? "on" : "off"; +} + +const char* EmptyToLabel(const std::string& value, const char* fallback) +{ + return value.empty() ? fallback : value.c_str(); +} + +void LogStartupSummary(int heart_fps, int player_id_start) +{ + sys_log(0, + "[STARTUP] locale=%s table_postfix=%s player_db=%s player_id_start=%d heart_fps=%d test_server=%s log=%s hotbackup=%s", + EmptyToLabel(g_stLocale, ""), + EmptyToLabel(g_stTablePostfix, ""), + EmptyToLabel(g_stPlayerDBName, ""), + player_id_start, + heart_fps, + BoolState(g_test_server), + BoolState(g_log != 0), + BoolState(g_bHotBackup) + ); + + sys_log(0, + "[STARTUP] cache_flush player=%d item=%d pricelist=%d logout=%d locale_name_column=%s", + g_iPlayerCacheFlushSeconds, + g_iItemCacheFlushSeconds, + g_iItemPriceListTableCacheFlushSeconds, + g_iLogoutSeconds, + EmptyToLabel(g_stLocaleNameColumn, "") + ); +} +} + void emergency_sig(int sig) { if (sig == SIGSEGV) @@ -374,6 +411,8 @@ int Start() return false; } + LogStartupSummary(heart_beat, iIDStart); + #ifndef OS_WINDOWS signal(SIGUSR1, emergency_sig); #endif @@ -409,4 +448,3 @@ const char * GetPlayerDBName() { return g_stPlayerDBName.c_str(); } - diff --git a/src/game/main.cpp b/src/game/main.cpp index bcedeab..ef74890 100644 --- a/src/game/main.cpp +++ b/src/game/main.cpp @@ -167,6 +167,64 @@ void ShutdownOnFatalError() namespace { + const char* BoolState(bool value) + { + return value ? "on" : "off"; + } + + const char* EmptyToLabel(const char* value, const char* fallback) + { + return (value && *value) ? value : fallback; + } + + const char* EmptyToLabel(const std::string& value, const char* fallback) + { + return value.empty() ? fallback : value.c_str(); + } + + void LogStartupSummary() + { +#ifdef ENABLE_PROXY_IP + const char* proxy_ip = EmptyToLabel(g_stProxyIP, ""); +#else + const char* proxy_ip = ""; +#endif + + sys_log(0, + "[STARTUP] mode=%s channel=%u bind=%s:%u p2p=%s:%u db=%s:%u locale=%s quest_dir=%s", + g_bAuthServer ? "auth" : "game", + g_bChannel, + EmptyToLabel(g_szPublicIP, "0.0.0.0"), mother_port, + EmptyToLabel(g_szPublicIP, "0.0.0.0"), p2p_port, + EmptyToLabel(db_addr, ""), db_port, + EmptyToLabel(g_stLocale, ""), + EmptyToLabel(g_stQuestDir, "") + ); + + sys_log(0, + "[STARTUP] users limit=%d full=%d busy=%d local=%u p2p_peers=%d regen=%s admin_page=%s proxy=%s", + g_iUserLimit, + g_iFullUserCount, + g_iBusyUserCount, + DESC_MANAGER::instance().GetLocalUserCount(), + P2P_MANAGER::instance().GetDescCount(), + BoolState(!g_bNoRegen), + BoolState(!g_stAdminPagePassword.empty()), + proxy_ip + ); + + sys_log(0, + "[STARTUP] features client_version_check=%s guild_mark_server=%s mark_min_level=%u empire_whisper=%s auth_master=%s:%u test_server=%d", + BoolState(g_bCheckClientVersion), + BoolState(guild_mark_server), + guild_mark_min_level, + BoolState(g_bEmpireWhisper), + EmptyToLabel(g_stAuthMasterIP, ""), + g_wAuthMasterPort, + test_server + ); + } + struct SendDisconnectFunc { void operator () (LPDESC d) @@ -594,6 +652,8 @@ int start(int argc, char **argv) LoadSpamDB(); } + LogStartupSummary(); + signal_timer_enable(30); return 1; } @@ -778,4 +838,3 @@ int io_loop(LPFDWATCH fdw) return 1; } - diff --git a/src/libthecore/socket.cpp b/src/libthecore/socket.cpp index b99786e..4c070e9 100644 --- a/src/libthecore/socket.cpp +++ b/src/libthecore/socket.cpp @@ -10,6 +10,31 @@ void socket_timeout(socket_t s, long sec, long usec); void socket_reuse(socket_t s); void socket_keepalive(socket_t s); +namespace +{ +bool socket_accept_should_retry() +{ +#ifdef OS_WINDOWS + const int wsa_error = WSAGetLastError(); + return wsa_error == WSAEWOULDBLOCK || wsa_error == WSAEINTR; +#else +#ifdef EINTR + if (errno == EINTR) + return true; +#endif +#ifdef EAGAIN + if (errno == EAGAIN) + return true; +#endif +#ifdef EWOULDBLOCK + if (errno == EWOULDBLOCK) + return true; +#endif + return false; +#endif +} +} + int socket_read(socket_t desc, char* read_point, size_t space_left) { int ret; @@ -206,6 +231,8 @@ socket_t socket_accept(socket_t s, struct sockaddr_in *peer) if ((desc = accept(s, (struct sockaddr *) peer, &i)) == -1) { + if (socket_accept_should_retry()) + return -1; sys_err("accept: %s (fd %d)", strerror(errno), s); return -1; }