Allow EAGAIN failures

Certain devices are known to return EAGAIN failures when read
too frequently, so be tolerant of them.

On startup, the code will retry for up to a second to get a good
first reading, and then in the main loop the code will just stick
with the current value if it fails that way.

Resolves openbmc/openbmc#2038

Change-Id: I7621aa30429c43276239982a03ec3eef02ce9c6e
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/sysfs.hpp b/sysfs.hpp
index ada73e8..b4709eb 100644
--- a/sysfs.hpp
+++ b/sysfs.hpp
@@ -1,10 +1,29 @@
 #pragma once
 
+#include <exception>
 #include <fstream>
 #include <string>
 
 namespace sysfs {
 
+/**
+ * @class DeviceBusyException
+ *
+ * An internal exception which will be thrown when
+ * readSysfsWithCallout() hits an EAGAIN.  Will never bubble
+ * up to terminate the application, nor does it need to be
+ * reported.
+ */
+class DeviceBusyException : public std::runtime_error
+{
+    public:
+
+        DeviceBusyException(const std::string& path) :
+            std::runtime_error(path + " busy")
+        {
+        }
+};
+
 inline std::string make_sysfs_path(const std::string& path,
                                    const std::string& type,
                                    const std::string& id,
@@ -37,6 +56,8 @@
  *  @param[in] type - The hwmon type (ex. temp).
  *  @param[in] id - The hwmon id (ex. 1).
  *  @param[in] sensor - The hwmon sensor (ex. input).
+ *  @param[in] throwDeviceBusy - will throw a DeviceBusyException
+ *             on an EAGAIN errno instead of an error log exception.
  *
  *  @returns - The read value.
  */
@@ -44,7 +65,8 @@
                          const std::string& instance,
                          const std::string& type,
                          const std::string& id,
-                         const std::string& sensor);
+                         const std::string& sensor,
+                         bool throwDeviceBusy = true);
 
  /** @brief Write a hwmon sysfs value
   *