From 2123696e4de17f3f98f12581b2ca6f1ff1500b07 Mon Sep 17 00:00:00 2001
From: Carl Philipp Klemm <philipp@uvos.xyz>
Date: Tue, 31 Oct 2023 16:35:44 +0100
Subject: [PATCH] Add a timeout to biocontrol waiting, and retry if biocontrol
 fails

---
 biocontrol.cpp | 43 ++++++++++++++++++++++++++++++-------------
 biocontrol.h   |  8 ++++----
 2 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/biocontrol.cpp b/biocontrol.cpp
index 122f253..d0ea035 100644
--- a/biocontrol.cpp
+++ b/biocontrol.cpp
@@ -1,6 +1,8 @@
 #include "biocontrol.h"
 
+#include <chrono>
 #include <string>
+#include <thread>
 #include <unistd.h>
 #include <errno.h>
 #include <stdexcept>
@@ -11,6 +13,7 @@
 #include <errno.h>
 #include <sstream>
 #include <fstream>
+#include <signal.h>
 
 #include "log.h"
 
@@ -52,6 +55,11 @@ void BioControl::execBiocontrol(const std::string& command, const std::string& u
 	{
 		int biopipe = open(biopipefilename, O_RDONLY | O_CLOEXEC);
 
+		if(biopipe < 0)
+		{
+			kill(childPid, SIGTERM);
+			throw std::runtime_error(std::string(__func__) + ": unable to open pipe: " + std::string(strerror(errno)));
+		}
 
 		if(biopipe >= 0)
 		{
@@ -65,21 +73,29 @@ void BioControl::execBiocontrol(const std::string& command, const std::string& u
 
 		Log(Log::DEBUG)<<"Wating for biocontrol to exit";
 		int exitCode;
-		waitpid(childPid, &exitCode, 0);
+		int timeout = 7200*2;
+		ret = 0;
+		while((ret = waitpid(childPid, &exitCode, WNOHANG)) == 0 && --timeout > 0)
+			std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+		if(ret == 0)
+		{
+			kill(childPid, SIGKILL);
+			throw std::runtime_error(std::string(__func__) + ": biocontol has hanged");
+		}
+
 		if(exitCode != 0)
 		{
 			close(biopipe);
 			throw std::runtime_error(std::string(__func__) + ": biocontol failed with: " + std::to_string(exitCode));
 		}
-
-		if(biopipe < 0)
-			throw std::runtime_error(std::string(__func__) + ": unable to open pipe: " + std::string(strerror(errno)));
 	}
 }
 
-bool BioControl::measure_eis(const std::filesystem::path& outPath, const std::string& userstr)
+bool BioControl::measure_eis(const std::filesystem::path& outPath, const std::string& userstr, bool retry)
 {
 	std::string mesurement;
+
 	try
 	{
 		execBiocontrol("geis", userstr, mesurement);
@@ -87,7 +103,8 @@ bool BioControl::measure_eis(const std::filesystem::path& outPath, const std::st
 	catch(const std::runtime_error& err)
 	{
 		Log(Log::ERROR)<<err.what();
-		return false;
+
+		return retry ? measure_eis(outPath, userstr, false) : false;
 	}
 
 	std::fstream file(outPath, std::ios_base::out);
@@ -103,7 +120,7 @@ bool BioControl::measure_eis(const std::filesystem::path& outPath, const std::st
 	return true;
 }
 
-bool BioControl::measure_ocv(float& ocv)
+bool BioControl::measure_ocv(float& ocv, bool retry)
 {
 	std::string mesurement;
 	try
@@ -114,12 +131,12 @@ bool BioControl::measure_ocv(float& ocv)
 	catch(const std::runtime_error& err)
 	{
 		Log(Log::ERROR)<<err.what();
-		return false;
+		return retry ? measure_ocv(ocv, false) : false;
 	}
 	catch(const std::invalid_argument& err)
 	{
 		Log(Log::ERROR)<<"Could not convert "<<mesurement<<": "<<err.what();
-		return false;
+		return retry ? measure_ocv(ocv, false) : false;
 	}
 
 	return true;
@@ -132,12 +149,12 @@ bool BioControl::shorted(bool& shorted)
 	return true;
 }
 
-bool BioControl::charge(float fraction, float current, const std::filesystem::path& outPath, const std::string& userstr)
+bool BioControl::charge(float fraction, float current, const std::filesystem::path& outPath, const std::string& userstr, bool retry)
 {
-	return chargeToVoltage(3.1 + fraction*(4.2-3.1), current, outPath, userstr);
+	return chargeToVoltage(3.1 + fraction*(4.2-3.1), current, outPath, userstr, retry);
 }
 
-bool BioControl::chargeToVoltage(float voltage, float current, const std::filesystem::path& outPath, const std::string& userstr)
+bool BioControl::chargeToVoltage(float voltage, float current, const std::filesystem::path& outPath, const std::string& userstr, bool retry)
 {
 	float ocv;
 	bool ret = measure_ocv(ocv);
@@ -163,7 +180,7 @@ bool BioControl::chargeToVoltage(float voltage, float current, const std::filesy
 	catch(const std::runtime_error& err)
 	{
 		Log(Log::ERROR)<<err.what();
-		return false;
+		return retry ? chargeToVoltage(voltage, current, outPath, userstr, false) : false;
 	}
 
 	std::fstream file(outPath, std::ios_base::out);
diff --git a/biocontrol.h b/biocontrol.h
index 21b3985..957c9be 100644
--- a/biocontrol.h
+++ b/biocontrol.h
@@ -16,9 +16,9 @@ public:
 	BioControl() = default;
 	BioControl(const std::filesystem::path& exepath, const std::string& ipAddr);
 
-	bool measure_eis(const std::filesystem::path& outPath, const std::string& userstr);
-	bool measure_ocv(float& ocv);
+	bool measure_eis(const std::filesystem::path& outPath, const std::string& userstr, bool retry = true);
+	bool measure_ocv(float& ocv, bool retry = true);
 	bool shorted(bool& shorted);
-	bool charge(float fraction, float current, const std::filesystem::path& outPath, const std::string& userstr);
-	bool chargeToVoltage(float voltage, float current, const std::filesystem::path& outPath, const std::string& userstr);
+	bool charge(float fraction, float current, const std::filesystem::path& outPath, const std::string& userstr, bool retry = true);
+	bool chargeToVoltage(float voltage, float current, const std::filesystem::path& outPath, const std::string& userstr, bool retry = true);
 };
-- 
GitLab