Fix(logger): preserve queued logs on shutdown; record exit signal

This commit is contained in:
yuanyuanxiang
2026-05-27 08:51:49 +02:00
parent 268a427172
commit 1fd431ba76
3 changed files with 37 additions and 4 deletions

View File

@@ -228,16 +228,19 @@ private:
} }
// 后台线程处理日志 // 后台线程处理日志
// 退出语义stop() 设 running=false 后,本线程必须把队列里**已入队**的日志
// 全部刷盘再退出。否则进程死亡前最后几条 Mprintf包括退出原因会丢失。
void processLogs() void processLogs()
{ {
threadRun = true; threadRun = true;
while (running) { while (true) {
std::unique_lock<std::mutex> lock(queueMutex); std::unique_lock<std::mutex> lock(queueMutex);
cv.wait(lock, [this]() { cv.wait(lock, [this]() {
return !running || !logQueue.empty(); return !running || !logQueue.empty();
}); });
while (running && !logQueue.empty()) { // drain不带 running 判断,确保 stop() 时残留条目也写完
while (!logQueue.empty()) {
std::string logEntry = logQueue.front(); std::string logEntry = logQueue.front();
logQueue.pop(); logQueue.pop();
lock.unlock(); lock.unlock();
@@ -247,7 +250,9 @@ private:
lock.lock(); lock.lock();
} }
lock.unlock();
// 队列已空再决定要不要退出
if (!running) break;
} }
threadRun = false; threadRun = false;
} }

View File

@@ -786,8 +786,12 @@ static void daemonize()
} }
// 信号处理:收到 SIGTERM/SIGINT 时优雅退出 // 信号处理:收到 SIGTERM/SIGINT 时优雅退出
// 注意handler 内不能调 MprintfLogger 用 mutex/string/condvar非 async-signal-safe
// 只在这里记 sig_atomic_t 标志位main 退出循环后再补一行日志。
static volatile sig_atomic_t g_lastSignal = 0;
static void signalHandler(int sig) static void signalHandler(int sig)
{ {
g_lastSignal = sig;
g_bExit = S_CLIENT_EXIT; g_bExit = S_CLIENT_EXIT;
} }
@@ -1060,6 +1064,14 @@ int main(int argc, char* argv[])
} }
} }
// 退出原因留痕signal handler 不能直接打日志,在这里补一行。
if (g_lastSignal != 0) {
Mprintf(">>> Exit by signal %d (g_bExit=%d)\n",
(int)g_lastSignal, (int)g_bExit);
} else {
Mprintf(">>> Exit normally (g_bExit=%d)\n", (int)g_bExit);
}
Logger::getInstance().stop(); Logger::getInstance().stop();
removePidFile(); removePidFile();
return 0; return 0;

View File

@@ -604,9 +604,13 @@ static void fillLoginInfo(LOGIN_INFOR& info)
// ============== Signal Handling ============== // ============== Signal Handling ==============
// 注意signal handler 内不能调 NSLog/MprintfNSLog 走 Foundation 锁,
// Mprintf 走 Logger mutex/condvar都不是 async-signal-safe。只在这里
// 记 sig_atomic_t 标志位main 退出循环后再补一行日志。
static volatile sig_atomic_t g_lastSignal = 0;
static void signalHandler(int sig) static void signalHandler(int sig)
{ {
NSLog(@"Received signal %d, shutting down...", sig); g_lastSignal = sig;
g_running = false; g_running = false;
g_bExit = S_CLIENT_EXIT; // 通知所有工作线程退出 g_bExit = S_CLIENT_EXIT; // 通知所有工作线程退出
} }
@@ -934,6 +938,14 @@ int main(int argc, const char* argv[])
} }
} }
// 退出原因留痕signal handler 不能直接打日志,在这里补一行。
if (g_lastSignal != 0) {
Mprintf(">>> Exit by signal %d (g_bExit=%d)\n",
(int)g_lastSignal, (int)g_bExit);
} else {
Mprintf(">>> Exit normally (g_bExit=%d)\n", (int)g_bExit);
}
NSLog(@"Shutting down..."); NSLog(@"Shutting down...");
// Release power assertions // Release power assertions
@@ -944,6 +956,10 @@ int main(int argc, const char* argv[])
// Display assertion is managed by ScreenHandler (released in stop()) // Display assertion is managed by ScreenHandler (released in stop())
// powerActivity is automatically released when exiting @autoreleasepool // powerActivity is automatically released when exiting @autoreleasepool
(void)powerActivity; // Suppress unused variable warning (void)powerActivity; // Suppress unused variable warning
// 显式停止日志,确保上面 Mprintf 的退出原因落盘。
// 不依赖 ~Logger() 的静态析构次序,避免后续新增日志相关静态对象时踩坑。
Logger::getInstance().stop();
} }
return 0; return 0;