Skip to content

Commit ecb5f68

Browse files
committed
fix: properly send off signal when shutting down
1 parent d29342d commit ecb5f68

1 file changed

Lines changed: 75 additions & 19 deletions

File tree

src_desktop/main.cpp

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <shared/desktop/glfw.h>
2323
#include "spdlog/cfg/env.h"
2424
#include <csignal>
25+
#include <future>
26+
#include <chrono>
2527

2628
// Third-party includes
2729
#include <fmt/format.h>
@@ -64,19 +66,59 @@ static auto DISPLAY_APP_NAME = "LED Matrix Controller";
6466
static bool showMainWindow = false;
6567

6668
#ifdef _WIN32
69+
// Global variables for shutdown handling on Windows
70+
static std::string g_shutdown_hostname;
71+
static uint16_t g_shutdown_port = 0;
72+
static bool g_should_turn_off_on_exit = false;
73+
6774
// Console control handler for Windows
6875
static BOOL WINAPI console_ctrl_handler(DWORD ctrlType) {
6976
// Request graceful shutdown
7077
shouldExit = true;
78+
// Attempt to turn off matrix during shutdown on Windows
79+
if (g_should_turn_off_on_exit && !g_shutdown_hostname.empty() && g_shutdown_port > 0) {
80+
spdlog::info("Received shutdown signal, turning Matrix OFF.");
81+
try {
82+
auto url = fmt::format("http://{}:{}/set_enabled?enabled=false", g_shutdown_hostname, g_shutdown_port);
83+
cpr::Response response = cpr::Get(cpr::Url(url), cpr::Timeout{3000L}); // 3 second timeout
84+
if (response.error) {
85+
spdlog::error("Failed to turn off matrix during shutdown: {}", response.error.message);
86+
} else {
87+
spdlog::info("Matrix turned OFF during shutdown.");
88+
}
89+
} catch (const std::exception &e) {
90+
spdlog::error("Exception while turning off matrix during shutdown: {}", e.what());
91+
}
92+
}
7193
// Indicate we've handled the event so the process isn't terminated immediately
7294
return TRUE;
7395
}
7496
#else
97+
// Global variables for shutdown handling on Linux
98+
static std::string g_shutdown_hostname;
99+
static uint16_t g_shutdown_port = 0;
100+
static bool g_should_turn_off_on_exit = false;
75101
// Use sig_atomic_t for async-signal-safety
76102
static volatile sig_atomic_t signalReceived = 0;
103+
77104
static void signal_handler(int /*signum*/) {
78105
signalReceived = 1;
79106
shouldExit = true;
107+
// Attempt to turn off matrix during shutdown on Linux
108+
if (g_should_turn_off_on_exit && !g_shutdown_hostname.empty() && g_shutdown_port > 0) {
109+
spdlog::info("Received shutdown signal, turning Matrix OFF.");
110+
try {
111+
auto url = fmt::format("http://{}:{}/set_enabled?enabled=false", g_shutdown_hostname, g_shutdown_port);
112+
cpr::Response response = cpr::Get(cpr::Url(url), cpr::Timeout{3000L}); // 3 second timeout
113+
if (response.error) {
114+
spdlog::error("Failed to turn off matrix during shutdown: {}", response.error.message);
115+
} else {
116+
spdlog::info("Matrix turned OFF during shutdown.");
117+
}
118+
} catch (const std::exception &e) {
119+
spdlog::error("Exception while turning off matrix during shutdown: {}", e.what());
120+
}
121+
}
80122
}
81123
#endif
82124

@@ -91,24 +133,31 @@ static void window_iconify_callback(GLFWwindow *window, const int iconified) {
91133
}
92134
}
93135

94-
// ----- Function to change matrix status ----
95-
static void change_matrix_status(const std::string &hostname, uint16_t port, bool turnOn) {
96-
std::thread([hostname, port, turnOn]() {
97-
try {
98-
auto url = fmt::format("http://{}:{}/set_enabled?enabled={}", hostname, port,
99-
turnOn ? "true" : "false");
100-
101-
cpr::Response response = cpr::Get(cpr::Url(url));
102-
if (response.error) {
103-
spdlog::error("Failed to change matrix status: {}", response.error.message);
104-
} else {
105-
spdlog::info("Matrix turned {} successfully.", turnOn ? "on" : "off");
106-
}
107-
} catch (const std::exception &e) {
108-
spdlog::error("Exception while changing matrix status: {}", e.what());
109-
}
110-
})
111-
.detach();
136+
// ----- Function to change matrix status (synchronous with timeout) ----
137+
static void change_matrix_status(const std::string &hostname, uint16_t port, bool turnOn, bool waitForCompletion = false) {
138+
auto task = [hostname, port, turnOn]() {
139+
try {
140+
auto url = fmt::format("http://{}:{}/set_enabled?enabled={}", hostname, port,
141+
turnOn ? "true" : "false");
142+
143+
cpr::Response response = cpr::Get(cpr::Url(url), cpr::Timeout{5000L}); // 5 second timeout
144+
if (response.error) {
145+
spdlog::error("Failed to change matrix status: {}", response.error.message);
146+
} else {
147+
spdlog::info("Matrix turned {} successfully.", turnOn ? "on" : "off");
148+
}
149+
} catch (const std::exception &e) {
150+
spdlog::error("Exception while changing matrix status: {}", e.what());
151+
}
152+
};
153+
154+
if (waitForCompletion) {
155+
// Synchronous call for shutdown scenarios
156+
task();
157+
} else {
158+
// Asynchronous call for normal operation
159+
std::thread(task).detach();
160+
}
112161
}
113162

114163
// ---- Tray setup ----
@@ -162,6 +211,12 @@ int run_app(int argc, char *argv[]) {
162211
plugin->load_config(cfg->getPluginSetting(plName));
163212
}
164213

214+
// Store shutdown configuration in global variables for signal handlers
215+
General &generalCfgRef = cfg->getGeneralConfig();
216+
g_shutdown_hostname = generalCfgRef.getHostnameCopy();
217+
g_shutdown_port = generalCfgRef.getPort();
218+
g_should_turn_off_on_exit = generalCfgRef.isTurnMatrixOffOnExit();
219+
165220
static WebsocketClient *ws;
166221
static UpdateChecker::UpdateManager updateManager;
167222
static MatrixVersionChecker::MatrixVersionManager matrixVersionManager;
@@ -548,7 +603,8 @@ int run_app(int argc, char *argv[]) {
548603
auto port = generalCfg.getPort();
549604
if (generalCfg.isTurnMatrixOffOnExit()) {
550605
spdlog::info("Turning Matrix OFF on exit.");
551-
change_matrix_status(hostname, port, false);
606+
// Use synchronous call on exit to ensure completion before shutdown
607+
change_matrix_status(hostname, port, false, true);
552608
}
553609
}
554610

0 commit comments

Comments
 (0)