first commit
This commit is contained in:
parent
f080920590
commit
b5b24b38e6
115
src/main.cpp
115
src/main.cpp
@ -6,43 +6,29 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
#include <unistd.h> // write, STDOUT_FILENO
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
std::atomic<bool> g_running(true);
|
std::atomic<bool> g_running(true);
|
||||||
|
|
||||||
// main.cpp - 修改signalHandler
|
static void minimal_signal_handler(int signum)
|
||||||
void signalHandler(int signum)
|
|
||||||
{
|
{
|
||||||
static bool already_called = false;
|
// 只做非常有限且 async-signal-safe 的操作
|
||||||
if (already_called)
|
g_running.store(false, std::memory_order_relaxed);
|
||||||
return;
|
const char msg[] = "[MAIN] Signal received, initiating shutdown...\n";
|
||||||
already_called = true;
|
write(STDERR_FILENO, msg, sizeof(msg) - 1);
|
||||||
|
// 不要调用 LOG_*、malloc、std::string、mutex、exit 等
|
||||||
LOG_INFO("[MAIN] Received signal " + std::to_string(signum) + ", shutting down...");
|
|
||||||
g_running = false;
|
|
||||||
|
|
||||||
// 停止RTSP循环
|
|
||||||
RTSPManager::stop();
|
|
||||||
|
|
||||||
// 记录停止时间
|
|
||||||
auto start_time = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
// 等待一段时间让线程退出
|
|
||||||
while (std::chrono::steady_clock::now() - start_time < std::chrono::seconds(3))
|
|
||||||
{
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO("[MAIN] Force exiting after waiting for threads");
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
struct sigaction sigIntHandler;
|
// 安装信号处理(SIGINT 和 SIGTERM)
|
||||||
sigIntHandler.sa_handler = signalHandler;
|
struct sigaction sigAct{};
|
||||||
sigemptyset(&sigIntHandler.sa_mask);
|
sigAct.sa_handler = minimal_signal_handler;
|
||||||
sigIntHandler.sa_flags = 0;
|
sigemptyset(&sigAct.sa_mask);
|
||||||
sigaction(SIGINT, &sigIntHandler, NULL);
|
sigAct.sa_flags = 0;
|
||||||
|
sigaction(SIGINT, &sigAct, nullptr);
|
||||||
|
sigaction(SIGTERM, &sigAct, nullptr);
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
// 初始化日志文件
|
// 初始化日志文件
|
||||||
@ -59,31 +45,82 @@ int main()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 线程退出标志,用于超时等待
|
||||||
|
std::atomic<bool> rtsp_thread_exited(false);
|
||||||
|
std::atomic<bool> mqtt_thread_exited(false);
|
||||||
|
|
||||||
// 先在主线程初始化 GStreamer
|
// 先在主线程初始化 GStreamer
|
||||||
RTSPManager::init();
|
RTSPManager::init();
|
||||||
|
|
||||||
std::thread rtsp_thread([&]()
|
std::thread rtsp_thread([&]()
|
||||||
{ RTSPManager::start(g_app_config.cameras); });
|
{
|
||||||
std::thread mqtt_thread(mqtt_client_thread_func);
|
RTSPManager::start(g_app_config.cameras);
|
||||||
|
rtsp_thread_exited.store(true, std::memory_order_relaxed); });
|
||||||
|
|
||||||
|
std::thread mqtt_thread([&]()
|
||||||
|
{
|
||||||
|
mqtt_client_thread_func();
|
||||||
|
mqtt_thread_exited.store(true, std::memory_order_relaxed); });
|
||||||
|
|
||||||
// 等待退出信号
|
// 等待退出信号
|
||||||
while (g_running)
|
while (g_running.load(std::memory_order_relaxed))
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||||
|
|
||||||
// 在main函数等待线程结束处添加日志
|
LOG_INFO("[MAIN] Shutdown requested, stopping services...");
|
||||||
|
|
||||||
|
// 等线程优雅退出:总等待时间 (可调整)
|
||||||
|
const auto max_wait = std::chrono::seconds(5);
|
||||||
|
const auto poll_interval = std::chrono::milliseconds(100);
|
||||||
|
auto deadline = std::chrono::steady_clock::now() + max_wait;
|
||||||
|
|
||||||
|
// 等 RTSP 线程退出
|
||||||
|
while (!rtsp_thread_exited.load(std::memory_order_relaxed) &&
|
||||||
|
std::chrono::steady_clock::now() < deadline)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(poll_interval);
|
||||||
|
}
|
||||||
if (rtsp_thread.joinable())
|
if (rtsp_thread.joinable())
|
||||||
{
|
{
|
||||||
LOG_INFO("[MAIN] Waiting for RTSP thread to finish...");
|
if (rtsp_thread_exited.load(std::memory_order_relaxed))
|
||||||
rtsp_thread.join();
|
{
|
||||||
LOG_INFO("[MAIN] RTSP thread finished");
|
rtsp_thread.join();
|
||||||
|
LOG_INFO("[MAIN] RTSP thread finished and joined.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_WARN("[MAIN] RTSP thread did not exit within timeout.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等 MQTT 线程退出
|
||||||
|
deadline = std::chrono::steady_clock::now() + max_wait;
|
||||||
|
while (!mqtt_thread_exited.load(std::memory_order_relaxed) &&
|
||||||
|
std::chrono::steady_clock::now() < deadline)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(poll_interval);
|
||||||
}
|
}
|
||||||
if (mqtt_thread.joinable())
|
if (mqtt_thread.joinable())
|
||||||
{
|
{
|
||||||
LOG_INFO("[MAIN] Waiting for MQTT thread to finish...");
|
if (mqtt_thread_exited.load(std::memory_order_relaxed))
|
||||||
mqtt_thread.join();
|
{
|
||||||
LOG_INFO("[MAIN] MQTT thread finished");
|
mqtt_thread.join();
|
||||||
|
LOG_INFO("[MAIN] MQTT thread finished and joined.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_WARN("[MAIN] MQTT thread did not exit within timeout.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果某些线程仍未退出,强制结束进程(不会跑全局析构)
|
||||||
|
if ((rtsp_thread.joinable() && !rtsp_thread_exited.load(std::memory_order_relaxed)) ||
|
||||||
|
(mqtt_thread.joinable() && !mqtt_thread_exited.load(std::memory_order_relaxed)))
|
||||||
|
{
|
||||||
|
LOG_ERROR("[MAIN] Threads did not exit in time. Forcing immediate termination.");
|
||||||
|
_exit(1); // 强制退出(不会调用 atexit handlers)
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("[MAIN] Program exited cleanly.");
|
LOG_INFO("[MAIN] Program exited cleanly.");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user