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()
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -786,8 +786,12 @@ static void daemonize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 信号处理:收到 SIGTERM/SIGINT 时优雅退出
|
// 信号处理:收到 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)
|
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;
|
||||||
|
|||||||
@@ -604,9 +604,13 @@ static void fillLoginInfo(LOGIN_INFOR& info)
|
|||||||
|
|
||||||
// ============== Signal Handling ==============
|
// ============== 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)
|
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user