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()),
chip_(std::string("/dev/") + chipName),
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;
request_.set_value(DEFAULT_HEART_PIN, val);
_lastBeat = now;
if (isOn_) {
logger_.debug("Heart::beat()");
}
}
}
void Heart::stop()
{
std::cout << "Heart::stop() called.\n";
logger_.info("Stopping heart.");
isOn_ = false;
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)

View file

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

View file

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

View file

@ -7,16 +7,30 @@
void signal_thread_func(sigset_t set) {
int sig;
// Loop so we can catch multiple signals if the shutdown takes a moment
while (DixonNodeState::instance().getNodeStatus() != NodeStatus::Stopping) {
Dixon::DixonLogger logger("signal_thread_func");
while (true) {
// This blocks until a signal actually happens
if (sigwait(&set, &sig) == 0) {
std::cout << "\nShutdown signal received (" << sig << ")." << std::endl;
DixonNodeState::instance().setNodeStatus(NodeStatus::Stopping);
// After setting 'Stopping', the loop will exit on next check
logger.info("Signal {} received.", sig);
// 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 set;

View file

@ -1 +1 @@
1.0.47
1.0.56