Fix(logger): preserve queued logs on shutdown; record exit signal
This commit is contained in:
@@ -228,16 +228,19 @@ private:
|
||||
}
|
||||
|
||||
// 后台线程处理日志
|
||||
// 退出语义:stop() 设 running=false 后,本线程必须把队列里**已入队**的日志
|
||||
// 全部刷盘再退出。否则进程死亡前最后几条 Mprintf(包括退出原因)会丢失。
|
||||
void processLogs()
|
||||
{
|
||||
threadRun = true;
|
||||
while (running) {
|
||||
while (true) {
|
||||
std::unique_lock<std::mutex> lock(queueMutex);
|
||||
cv.wait(lock, [this]() {
|
||||
return !running || !logQueue.empty();
|
||||
});
|
||||
|
||||
while (running && !logQueue.empty()) {
|
||||
// drain:不带 running 判断,确保 stop() 时残留条目也写完
|
||||
while (!logQueue.empty()) {
|
||||
std::string logEntry = logQueue.front();
|
||||
logQueue.pop();
|
||||
lock.unlock();
|
||||
@@ -247,7 +250,9 @@ private:
|
||||
|
||||
lock.lock();
|
||||
}
|
||||
lock.unlock();
|
||||
|
||||
// 队列已空再决定要不要退出
|
||||
if (!running) break;
|
||||
}
|
||||
threadRun = false;
|
||||
}
|
||||
|
||||
@@ -786,8 +786,12 @@ static void daemonize()
|
||||
}
|
||||
|
||||
// 信号处理:收到 SIGTERM/SIGINT 时优雅退出
|
||||
// 注意:handler 内不能调 Mprintf(Logger 用 mutex/string/condvar,非 async-signal-safe),
|
||||
// 只在这里记 sig_atomic_t 标志位,main 退出循环后再补一行日志。
|
||||
static volatile sig_atomic_t g_lastSignal = 0;
|
||||
static void signalHandler(int sig)
|
||||
{
|
||||
g_lastSignal = sig;
|
||||
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();
|
||||
removePidFile();
|
||||
return 0;
|
||||
|
||||
@@ -604,9 +604,13 @@ static void fillLoginInfo(LOGIN_INFOR& info)
|
||||
|
||||
// ============== Signal Handling ==============
|
||||
|
||||
// 注意:signal handler 内不能调 NSLog/Mprintf(NSLog 走 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)
|
||||
{
|
||||
NSLog(@"Received signal %d, shutting down...", sig);
|
||||
g_lastSignal = sig;
|
||||
g_running = false;
|
||||
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...");
|
||||
|
||||
// Release power assertions
|
||||
@@ -944,6 +956,10 @@ int main(int argc, const char* argv[])
|
||||
// Display assertion is managed by ScreenHandler (released in stop())
|
||||
// powerActivity is automatically released when exiting @autoreleasepool
|
||||
(void)powerActivity; // Suppress unused variable warning
|
||||
|
||||
// 显式停止日志,确保上面 Mprintf 的退出原因落盘。
|
||||
// 不依赖 ~Logger() 的静态析构次序,避免后续新增日志相关静态对象时踩坑。
|
||||
Logger::getInstance().stop();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user