Improves shutdown handling and adds logging

Adds logging to heart component and signal handler for improved debugging.
Changes signal handler to set a "StopPending" state to allow the main loop to handle shutdown.
Fixes a potential thread join issue during shutdown.
This commit is contained in:
Russell Gilbert 2026-02-20 17:07:10 +00:00
parent 3a4e00a409
commit adda211b76
5 changed files with 34 additions and 12 deletions

View file

@ -9,7 +9,8 @@ namespace cardio
: _lastBeat(std::chrono::steady_clock::now()), : _lastBeat(std::chrono::steady_clock::now()),
chip_(std::string("/dev/") + chipName), chip_(std::string("/dev/") + chipName),
isOn_(false), isOn_(false),
request_(get_line_request(chip_, lineOffset)) request_(get_line_request(chip_, lineOffset)),
logger_("Heart")
{ {
} }
@ -27,14 +28,19 @@ namespace cardio
const auto val = isOn_ ? gpiod::line::value::ACTIVE : gpiod::line::value::INACTIVE; const auto val = isOn_ ? gpiod::line::value::ACTIVE : gpiod::line::value::INACTIVE;
request_.set_value(DEFAULT_HEART_PIN, val); request_.set_value(DEFAULT_HEART_PIN, val);
_lastBeat = now; _lastBeat = now;
if (isOn_) {
logger_.debug("Heart::beat()");
}
} }
} }
void Heart::stop() void Heart::stop()
{ {
std::cout << "Heart::stop() called.\n"; logger_.info("Stopping heart.");
isOn_ = false; isOn_ = false;
request_.set_value(DEFAULT_HEART_PIN, gpiod::line::value::INACTIVE); request_.set_value(DEFAULT_HEART_PIN, gpiod::line::value::INACTIVE);
logger_.info("Stopped heart.");
} }
gpiod::line_request Heart::get_line_request(gpiod::chip& chip, const unsigned int lineOffset) gpiod::line_request Heart::get_line_request(gpiod::chip& chip, const unsigned int lineOffset)

View file

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "../Logging/DixonLogger.h"
#include <gpiod.hpp> #include <gpiod.hpp>
#include <chrono> #include <chrono>
@ -21,5 +22,6 @@ namespace cardio
gpiod::chip chip_; gpiod::chip chip_;
bool isOn_; bool isOn_;
gpiod::line_request request_; gpiod::line_request request_;
Dixon::DixonLogger logger_;
}; };
} }

View file

@ -37,14 +37,14 @@ void DixonBrain::stop()
state_.setNodeStatus(NodeStatus::Stopping); state_.setNodeStatus(NodeStatus::Stopping);
if (loopThread_.joinable())
loopThread_.join();
heart_.stop(); heart_.stop();
state_.setNodeStatus(NodeStatus::Stopped); state_.setNodeStatus(NodeStatus::Stopped);
logger_.info("DixonBrain stopped."); logger_.info("DixonBrain stopped.");
if (loopThread_.joinable())
loopThread_.join();
} }
void DixonBrain::runLoop() void DixonBrain::runLoop()

View file

@ -7,16 +7,30 @@
void signal_thread_func(sigset_t set) { void signal_thread_func(sigset_t set) {
int sig; int sig;
// Loop so we can catch multiple signals if the shutdown takes a moment Dixon::DixonLogger logger("signal_thread_func");
while (DixonNodeState::instance().getNodeStatus() != NodeStatus::Stopping) {
while (true) {
// This blocks until a signal actually happens
if (sigwait(&set, &sig) == 0) { if (sigwait(&set, &sig) == 0) {
std::cout << "\nShutdown signal received (" << sig << ")." << std::endl; logger.info("Signal {} received.", sig);
DixonNodeState::instance().setNodeStatus(NodeStatus::Stopping);
// After setting 'Stopping', the loop will exit on next check // Set the state so the main loop starts the shutdown
DixonNodeState::instance().setNodeStatus(NodeStatus::StopPending);
// If you want to allow a "Force Quit" on the second Ctrl-C:
static int interrupt_count = 0;
if (++interrupt_count >= 3) {
logger.warn("Force quitting...");
exit(1);
}
}
// Check if the main thread has finished cleaning up
if (DixonNodeState::instance().getNodeStatus() == NodeStatus::Stopped) {
break;
} }
} }
} }
sigset_t prepare_signal_set() sigset_t prepare_signal_set()
{ {
sigset_t set; sigset_t set;

View file

@ -1 +1 @@
1.0.47 1.0.56