refactored FIFO handling
This commit is contained in:
@ -44,11 +44,30 @@ int WatchdogTask::performOperation() {
|
||||
<< strerror(errno) << std::endl;
|
||||
return -1;
|
||||
}
|
||||
// Clear FIFO by reading until it is empty.
|
||||
while (true) {
|
||||
ssize_t readBytes = read(fd, buf.data(), buf.size());
|
||||
if (readBytes < 0) {
|
||||
std::cerr << "Read error of FIFO: " << strerror(errno) << std::endl;
|
||||
} else if (readBytes == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
state = States::NOT_STARTED;
|
||||
|
||||
bool breakOuter = false;
|
||||
while (true) {
|
||||
WatchdogTask::LoopResult loopResult = watchdogLoop();
|
||||
if (not stateMachine(loopResult)) {
|
||||
watchdogLoop();
|
||||
while (not resultQueue.empty()) {
|
||||
auto nextRequest = resultQueue.front();
|
||||
if (not stateMachine(nextRequest)) {
|
||||
breakOuter = true;
|
||||
resultQueue.pop();
|
||||
break;
|
||||
}
|
||||
resultQueue.pop();
|
||||
}
|
||||
if (breakOuter) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -60,7 +79,7 @@ int WatchdogTask::performOperation() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
WatchdogTask::LoopResult WatchdogTask::watchdogLoop() {
|
||||
void WatchdogTask::watchdogLoop() {
|
||||
using namespace std::chrono_literals;
|
||||
struct pollfd waiter = {};
|
||||
waiter.fd = fd;
|
||||
@ -69,10 +88,12 @@ WatchdogTask::LoopResult WatchdogTask::watchdogLoop() {
|
||||
// Only poll one file descriptor with timeout
|
||||
switch (poll(&waiter, 1, watchdog::TIMEOUT_MS)) {
|
||||
case (0): {
|
||||
return LoopResult::TIMEOUT;
|
||||
resultQueue.push(LoopResult::TIMEOUT);
|
||||
return;
|
||||
}
|
||||
case (1): {
|
||||
return pollEvent(waiter);
|
||||
pollEvent(waiter);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
std::cerr << "Unknown poll error at " << watchdog::FIFO_NAME << ", error " << errno << ": "
|
||||
@ -80,50 +101,52 @@ WatchdogTask::LoopResult WatchdogTask::watchdogLoop() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return LoopResult::OK;
|
||||
}
|
||||
|
||||
WatchdogTask::LoopResult WatchdogTask::pollEvent(struct pollfd& waiter) {
|
||||
void WatchdogTask::pollEvent(struct pollfd& waiter) {
|
||||
if (waiter.revents & POLLIN) {
|
||||
ssize_t readLen = read(fd, buf.data(), buf.size());
|
||||
#if WATCHDOG_VERBOSE_LEVEL == 2
|
||||
std::cout << "Read " << readLen << " byte(s) on the pipe " << watchdog::FIFO_NAME << std::endl;
|
||||
#endif
|
||||
if (readLen < 0) {
|
||||
std::cerr << "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
|
||||
else if (readLen >= 1) {
|
||||
return parseCommand(readLen);
|
||||
resultQueue.push(LoopResult::OK);
|
||||
} else if (readLen >= 1) {
|
||||
parseCommands(readLen);
|
||||
}
|
||||
|
||||
} else if (waiter.revents & POLLERR) {
|
||||
std::cerr << "Poll error error on pipe " << watchdog::FIFO_NAME << std::endl;
|
||||
return LoopResult::FAULT;
|
||||
resultQueue.push(LoopResult::FAULT);
|
||||
} else if (waiter.revents & POLLHUP) {
|
||||
// Writer closed its end
|
||||
return LoopResult::HUNG_UP;
|
||||
resultQueue.push(LoopResult::HUNG_UP);
|
||||
}
|
||||
return LoopResult::FAULT;
|
||||
}
|
||||
|
||||
WatchdogTask::LoopResult WatchdogTask::parseCommand(ssize_t readLen) {
|
||||
char readChar = buf[0];
|
||||
// Cancel request
|
||||
if (readChar == watchdog::first::CANCEL_CHAR) {
|
||||
return LoopResult::CANCEL_REQ;
|
||||
} else if (readChar == watchdog::first::SUSPEND_CHAR) {
|
||||
// Suspend request
|
||||
return LoopResult::SUSPEND_REQ;
|
||||
} else if (readChar == watchdog::first::START_CHAR) {
|
||||
if (readLen == 2 and static_cast<char>(buf[1]) == watchdog::second::WATCH_FLAG) {
|
||||
return LoopResult::START_WITH_WATCH_REQ;
|
||||
void WatchdogTask::parseCommands(ssize_t readLen) {
|
||||
for (ssize_t idx = 0; idx < readLen; idx++) {
|
||||
char nextChar = buf[idx];
|
||||
// Cancel request
|
||||
if (nextChar == watchdog::first::CANCEL_CHAR) {
|
||||
resultQueue.push(LoopResult::CANCEL_REQ);
|
||||
} else if (nextChar == watchdog::first::SUSPEND_CHAR) {
|
||||
// Suspend request
|
||||
resultQueue.push(LoopResult::SUSPEND_REQ);
|
||||
} else if (nextChar == watchdog::first::START_CHAR) {
|
||||
if (idx < readLen - 1 and static_cast<char>(buf[idx + 1]) == watchdog::second::WATCH_FLAG) {
|
||||
resultQueue.push(LoopResult::START_WITH_WATCH_REQ);
|
||||
idx++;
|
||||
continue;
|
||||
}
|
||||
resultQueue.push(LoopResult::START_REQ);
|
||||
} else if (nextChar == watchdog::first::IDLE_CHAR) {
|
||||
resultQueue.push(LoopResult::OK);
|
||||
}
|
||||
return LoopResult::START_REQ;
|
||||
}
|
||||
// Everything else: All working as expected
|
||||
return LoopResult::OK;
|
||||
}
|
||||
|
||||
int WatchdogTask::performRunningOperation() {
|
||||
@ -167,11 +190,12 @@ int WatchdogTask::performNotRunningOperation(LoopResult type) {
|
||||
}
|
||||
|
||||
if (not notRunningStart.has_value()) {
|
||||
notRunningStart = std::chrono::system_clock::now();
|
||||
notRunningStart = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
if (obswRunning) {
|
||||
#if WATCHDOG_CREATE_FILE_IF_RUNNING == 1
|
||||
std::cout << "Removing " << watchdog::RUNNING_FILE_NAME << std::endl;
|
||||
if (std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) {
|
||||
int result = std::remove(watchdog::RUNNING_FILE_NAME.c_str());
|
||||
if (result != 0) {
|
||||
@ -184,7 +208,7 @@ int WatchdogTask::performNotRunningOperation(LoopResult type) {
|
||||
}
|
||||
|
||||
if (watchingObsw) {
|
||||
auto timeNotRunning = std::chrono::system_clock::now() - notRunningStart.value();
|
||||
auto timeNotRunning = std::chrono::steady_clock::now() - notRunningStart.value();
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(timeNotRunning).count() >
|
||||
watchdog::MAX_NOT_RUNNING_MS) {
|
||||
std::cout << "Restarting OBSW with systemctl" << std::endl;
|
||||
@ -269,7 +293,7 @@ bool WatchdogTask::stateMachine(LoopResult loopResult) {
|
||||
sleep = true;
|
||||
}
|
||||
if (sleep) {
|
||||
std::this_thread::sleep_for(1000ms);
|
||||
std::this_thread::sleep_for(500ms);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user