watchdog handling finished

This commit is contained in:
2021-07-29 16:31:04 +02:00
parent 983ce045a9
commit ff86c8af73
8 changed files with 179 additions and 45 deletions

View File

@ -9,6 +9,7 @@
#include <fcntl.h>
#include <iostream>
#include <fstream>
#include <thread>
#include <cstring>
#include <filesystem>
@ -54,21 +55,34 @@ int WatchdogTask::performOperation() {
break;
}
case(LoopResult::CANCEL_RQ): {
if(state == States::RUNNING) {
std::cout << "eive-watchdog: Received cancel request, closing watchdog.." << std::endl;
return 0;
}
case(LoopResult::SUSPEND_RQ): {
std::cout << "eive-watchdog: Suspending watchdog operations" << std::endl;
if(state == States::RUNNING or state == States::FAULTY) {
watchdogRunning = false;
state = States::SUSPENDED;
}
break;
}
case(LoopResult::TIMEOUT): {
std::cout << "eive-watchdog: The FIFO timed out!" << std::endl;
performTimeoutOperation();
break;
}
case(LoopResult::RESTART_RQ): {
if(state == States::SUSPENDED) {
if(state == States::SUSPENDED or state == States::FAULTY) {
state = States::RUNNING;
watchdogRunning = true;
performRunningOperation();
}
break;
}
case(LoopResult::FAULT): {
// Configuration error
std::cerr << "Fault has occured in watchdog loop" << std::endl;
}
}
}
if (close(fd) < 0) {
@ -81,7 +95,6 @@ int WatchdogTask::performOperation() {
WatchdogTask::LoopResult WatchdogTask::watchdogLoop() {
using namespace std::chrono_literals;
char readChar;
struct pollfd waiter = {};
waiter.fd = fd;
waiter.events = POLLIN;
@ -113,41 +126,7 @@ WatchdogTask::LoopResult WatchdogTask::watchdogLoop() {
return LoopResult::TIMEOUT;
}
case(1): {
if (waiter.revents & POLLIN) {
ssize_t readLen = read(fd, buf.data(), buf.size());
if (readLen < 0) {
std::cerr << "eive-watchdog: Read error on pipe " << watchdog::FIFO_NAME <<
", error " << errno << ": " << strerror(errno) << std::endl;
break;
}
for(ssize_t idx = 0; idx < readLen; idx++) {
readChar = buf[idx];
// Cancel request
if(readChar == 'c') {
return LoopResult::CANCEL_RQ;
}
// Begin request. Does not work if the operation was not suspended before
else if(readChar == 'b') {
return LoopResult::RESTART_RQ;
}
// Everything else: All working as expected
else {
}
}
#if WATCHDOG_VERBOSE_LEVEL == 2
std::cout << "Read " << readLen << " byte(s) on the pipe " << FIFO_NAME
<< std::endl;
#endif
}
else if(waiter.revents & POLLERR) {
std::cerr << "eive-watchdog: Poll error error on pipe " << watchdog::FIFO_NAME <<
std::endl;
}
else if (waiter.revents & POLLHUP) {
// Writer closed its end
}
break;
return pollEvent(waiter);
}
default: {
std::cerr << "eive-watchdog: Unknown poll error at " << watchdog::FIFO_NAME << ", error " <<
@ -157,3 +136,81 @@ WatchdogTask::LoopResult WatchdogTask::watchdogLoop() {
}
return LoopResult::OK;
}
WatchdogTask::LoopResult WatchdogTask::pollEvent(struct pollfd& waiter) {
if (waiter.revents & POLLIN) {
ssize_t readLen = read(fd, buf.data(), buf.size());
if (readLen < 0) {
std::cerr << "eive-watchdog: Read error on pipe " << watchdog::FIFO_NAME <<
", error " << errno << ": " << strerror(errno) << std::endl;
return LoopResult::OK;
}
#if WATCHDOG_VERBOSE_LEVEL == 2
std::cout << "Read " << readLen << " byte(s) on the pipe " << FIFO_NAME
<< std::endl;
#endif
return parseCommandByte(readLen);
}
else if(waiter.revents & POLLERR) {
std::cerr << "eive-watchdog: Poll error error on pipe " << watchdog::FIFO_NAME <<
std::endl;
return LoopResult::FAULT;
}
else if (waiter.revents & POLLHUP) {
// Writer closed its end
}
return LoopResult::FAULT;
}
WatchdogTask::LoopResult WatchdogTask::parseCommandByte(ssize_t readLen) {
for(ssize_t idx = 0; idx < readLen; idx++) {
char readChar = buf[idx];
// Cancel request
if(readChar == watchdog::CANCEL_CHAR) {
return LoopResult::CANCEL_RQ;
}
// Begin request. Does not work if the operation was not suspended before
else if(readChar == watchdog::RESTART_CHAR) {
return LoopResult::RESTART_RQ;
}
// Suspend request
else if(readChar == watchdog::SUSPEND_CHAR) {
return LoopResult::SUSPEND_RQ;
}
// Everything else: All working as expected
}
return LoopResult::OK;
}
int WatchdogTask::performRunningOperation() {
if(not obswRunning) {
obswRunning = true;
#if WATCHDOG_CREATE_FILE_IF_RUNNING == 1
if (not std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) {
std::ofstream obswRunningFile(watchdog::RUNNING_FILE_NAME);
if(not obswRunningFile.good()) {
std::cerr << "Creating file " << watchdog::RUNNING_FILE_NAME << " failed"
<< std::endl;
}
}
#endif
}
return 0;
}
int WatchdogTask::performTimeoutOperation() {
#if WATCHDOG_CREATE_FILE_IF_RUNNING == 1
if (std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) {
int result = std::remove(watchdog::RUNNING_FILE_NAME.c_str());
if(result != 0) {
std::cerr << "Removing " << watchdog::RUNNING_FILE_NAME << " failed with code " <<
errno << ": " << strerror(errno) << std::endl;
}
}
#endif
if(obswRunning) {
obswRunning = false;
}
return 0;
}

View File

@ -15,9 +15,11 @@ public:
enum class LoopResult {
OK,
SUSPEND_RQ,
CANCEL_RQ,
RESTART_RQ,
TIMEOUT
TIMEOUT,
FAULT
};
WatchdogTask();
@ -28,10 +30,17 @@ public:
private:
int fd = 0;
bool obswRunning = false;
bool watchdogRunning = false;
std::array<uint8_t, 64> buf;
States state = States::NOT_STARTED;
LoopResult watchdogLoop();
LoopResult pollEvent(struct pollfd& waiter);
LoopResult parseCommandByte(ssize_t readLen);
int performRunningOperation();
int performTimeoutOperation();
};
#endif /* WATCHDOG_WATCHDOG_H_ */

View File

@ -1,4 +1,5 @@
#include <cstdint>
#include <string>
#define WATCHDOG_VERBOSE_LEVEL 1
/**
@ -13,4 +14,11 @@ static constexpr int TIMEOUT_MS = 10 * 1000;
const std::string FIFO_NAME = "/tmp/watchdog-pipe";
const std::string RUNNING_FILE_NAME = "/tmp/obsw-running";
// Suspend watchdog operations temporarily
static constexpr char SUSPEND_CHAR = 's';
// Resume watchdog operations
static constexpr char RESTART_CHAR = 'b';
// Causes the watchdog to close down
static constexpr char CANCEL_CHAR = 'c';
}