// main.cpp #include "app_config.hpp" #include "rtsp_manager.hpp" #include "logger.hpp" #include "mqtt_client_wrapper.hpp" #include #include #include #include #include constexpr bool ENABLE_RTSP_THREAD = true; constexpr bool ENABLE_MQTT_THREAD = true; std::atomic g_running(true); static void minimal_signal_handler(int signum) { g_running.store(false, std::memory_order_relaxed); const char msg[] = "[MAIN] Signal received, initiating shutdown...\n"; write(STDERR_FILENO, msg, sizeof(msg) - 1); } int main() { struct sigaction sigAct{}; sigAct.sa_handler = minimal_signal_handler; sigemptyset(&sigAct.sa_mask); sigAct.sa_flags = 0; sigaction(SIGINT, &sigAct, nullptr); sigaction(SIGTERM, &sigAct, nullptr); signal(SIGPIPE, SIG_IGN); Logger::set_log_to_file(get_executable_dir_file_path("app.log")); try { g_app_config = AppConfig::load_from_file(get_executable_dir_file_path("config.json")); } catch (const std::exception &e) { LOG_ERROR(std::string("Failed to load config: ") + e.what()); return -1; } std::atomic rtsp_thread_exited(false); std::atomic mqtt_thread_exited(false); // 初始化 GStreamer RTSPManager::init(); std::thread rtsp_thread; std::thread mqtt_thread; if (ENABLE_RTSP_THREAD) { rtsp_thread = std::thread([&]() { RTSPManager::start(g_app_config.cameras); rtsp_thread_exited.store(true, std::memory_order_relaxed); }); LOG_INFO("[MAIN] RTSP thread started"); } else { LOG_INFO("[MAIN] RTSP thread disabled by toggle"); } if (ENABLE_MQTT_THREAD) { mqtt_thread = std::thread([&]() { mqtt_client_thread_func(); mqtt_thread_exited.store(true, std::memory_order_relaxed); }); LOG_INFO("[MAIN] MQTT thread started"); } else { LOG_INFO("[MAIN] MQTT thread disabled by toggle"); } while (g_running.load(std::memory_order_relaxed)) std::this_thread::sleep_for(std::chrono::milliseconds(200)); LOG_INFO("[MAIN] Shutdown requested, stopping services..."); const auto max_wait = std::chrono::seconds(5); const auto poll_interval = std::chrono::milliseconds(100); if (ENABLE_RTSP_THREAD) { RTSPManager::stop(); if (rtsp_thread.joinable()) rtsp_thread.join(); LOG_INFO("[MAIN] RTSP thread finished and joined."); } auto deadline = std::chrono::steady_clock::now() + max_wait; if (ENABLE_MQTT_THREAD) { 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_exited.load(std::memory_order_relaxed)) { mqtt_thread.join(); LOG_INFO("[MAIN] MQTT thread finished and joined."); } else { LOG_WARN("[MAIN] MQTT thread did not exit within timeout."); } } } bool any_failed = false; if (ENABLE_RTSP_THREAD && rtsp_thread.joinable() && !rtsp_thread_exited.load()) any_failed = true; if (ENABLE_MQTT_THREAD && mqtt_thread.joinable() && !mqtt_thread_exited.load()) any_failed = true; if (any_failed) { LOG_ERROR("[MAIN] Threads did not exit in time. Forcing immediate termination."); _exit(1); } LOG_INFO("[MAIN] Program exited cleanly."); return 0; }