Log failing path after sysfs access failures
Log failing device path and error after a sysfs access failure.
Gracefully exit rather than crash.
Change-Id: I41316e84a70ceda8c166f31ab3269f97978da3ab
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/Makefile.am b/Makefile.am
index 5ce260f..ee6e7a8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,8 +6,13 @@
phosphor_hwmon_readd_CFLAGS = $(SDBUSPLUS_CFLAGS)
noinst_LTLIBRARIES = libhwmon.la
-libhwmon_la_LDFLAGS = $(SDBUSPLUS_LIBS) $(PHOSPHOR_DBUS_INTERFACES_LIBS)
-libhwmon_la_CFLAGS = $(SDBUSPLUS_CFLAGS) $(PHOSPHOR_DBUS_INTERFACES_CFLAGS)
+libhwmon_la_LDFLAGS = \
+ $(SDBUSPLUS_LIBS) \
+ $(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+ $(PHOSPHOR_LOGGING_LIBS)
+libhwmon_la_CFLAGS = $(SDBUSPLUS_CFLAGS) \
+ $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
+ $(PHOSPHOR_LOGGING_CFLAGS)
libhwmon_la_SOURCES = \
argument.cpp \
diff --git a/configure.ac b/configure.ac
index 303d6ff..c7bfa46 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,6 +15,7 @@
# Checks for libraries.
PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus], [], [AC_MSG_ERROR(["sdbusplus required and not found."])])
PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces], [], [AC_MSG_ERROR(["phosphor-dbus-interfaces required and not found."])])
+PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging], [], [AC_MSG_ERROR(["phosphor-logging required and not found."])])
# Checks for typedefs, structures, and compiler characteristics.
AX_CXX_COMPILE_STDCXX_14([noext])
diff --git a/mainloop.cpp b/mainloop.cpp
index 31b02ac..0077d33 100644
--- a/mainloop.cpp
+++ b/mainloop.cpp
@@ -110,7 +110,9 @@
}
auto addValue(const SensorSet::key_type& sensor,
- const std::string& sysfsRoot, ObjectInfo& info)
+ const std::string& hwmonRoot,
+ const std::string& instance,
+ ObjectInfo& info)
{
static constexpr bool deferSignals = true;
@@ -119,14 +121,11 @@
auto& obj = std::get<Object>(info);
auto& objPath = std::get<std::string>(info);
- auto sysfsPath = make_sysfs_path(
- sysfsRoot,
- sensor.first,
- sensor.second,
- hwmon::entry::input);
- int val = 0;
- read_sysfs(sysfsPath, val);
-
+ int val = readSysfsWithCallout(hwmonRoot,
+ instance,
+ sensor.first,
+ sensor.second,
+ hwmon::entry::input);
auto iface = std::make_shared<ValueObject>(bus, objPath.c_str(), deferSignals);
iface->value(val);
@@ -180,8 +179,7 @@
void MainLoop::run()
{
// Check sysfs for available sensors.
- std::string hwmonPath = _hwmonRoot + '/' + _instance;
- auto sensors = std::make_unique<SensorSet>(hwmonPath);
+ auto sensors = std::make_unique<SensorSet>(_hwmonRoot + '/' + _instance);
for (auto& i : *sensors)
{
@@ -207,7 +205,7 @@
objectPath.append(label);
ObjectInfo info(&_bus, std::move(objectPath), Object());
- auto valueInterface = addValue(i.first, hwmonPath, info);
+ auto valueInterface = addValue(i.first, _hwmonRoot, _instance, info);
auto sensorValue = valueInterface->value();
addThreshold<WarningObject>(i.first, sensorValue, info);
addThreshold<CriticalObject>(i.first, sensorValue, info);
@@ -244,12 +242,11 @@
if (attrs.find(hwmon::entry::input) != attrs.end())
{
// Read value from sensor.
- int value = 0;
- read_sysfs(make_sysfs_path(hwmonPath,
- i.first.first, i.first.second,
- hwmon::entry::input),
- value);
-
+ int value = readSysfsWithCallout(_hwmonRoot,
+ _instance,
+ i.first.first,
+ i.first.second,
+ hwmon::entry::input);
auto& objInfo = std::get<ObjectInfo>(i.second);
auto& obj = std::get<Object>(objInfo);
diff --git a/sysfs.cpp b/sysfs.cpp
index f1f46db..0cc11ef 100644
--- a/sysfs.cpp
+++ b/sysfs.cpp
@@ -15,6 +15,7 @@
*/
#include <cstdlib>
#include <memory>
+#include <phosphor-logging/log.hpp>
#include "sysfs.hpp"
#include "util.hpp"
#include "directory.hpp"
@@ -51,4 +52,46 @@
return std::string();
}
+int readSysfsWithCallout(const std::string& root,
+ const std::string& instance,
+ const std::string& type,
+ const std::string& id,
+ const std::string& sensor)
+{
+ int value = 0;
+ std::string instancePath = root + '/' + instance;
+ std::string fullPath = make_sysfs_path(instancePath,
+ type, id, sensor);
+ std::ifstream ifs;
+
+ ifs.exceptions(std::ifstream::failbit
+ | std::ifstream::badbit
+ | std::ifstream::eofbit);
+ try
+ {
+ ifs.open(fullPath);
+ ifs >> value;
+ }
+ catch (const std::exception& e)
+ {
+ // Too many GCC bugs (53984, 66145) to do
+ // this the right way...
+ using Cleanup = phosphor::utility::Free<char>;
+
+ // errno should still reflect the error from the failing open
+ // or read system calls that got us here.
+ auto rc = errno;
+ std::string devicePath = instancePath + "/device";
+ auto real = std::unique_ptr<char, Cleanup>(
+ realpath(devicePath.c_str(), nullptr));
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ strerror(rc),
+ phosphor::logging::entry("CALLOUT_DEVICE_PATH=%s", real.get()),
+ phosphor::logging::entry("CALLOUT_ERRNO=%d", rc));
+ exit(EXIT_FAILURE);
+ }
+
+ return value;
+}
+
// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
diff --git a/sysfs.hpp b/sysfs.hpp
index 8f09e03..c38ed9e 100644
--- a/sysfs.hpp
+++ b/sysfs.hpp
@@ -40,4 +40,22 @@
*/
std::string findHwmon(const std::string& ofNode);
+/** @brief Read an hwmon sysfs value.
+ *
+ * Calls exit(3) with bad status on failure.
+ *
+ * @param[in] root - The hwmon class root.
+ * @param[in] instance - The hwmon instance (ex. hwmon1).
+ * @param[in] type - The hwmon type (ex. temp).
+ * @param[in] id - The hwmon id (ex. 1).
+ * @param[in] sensor - The hwmon sensor (ex. input).
+ *
+ * @returns - The read value.
+ */
+int readSysfsWithCallout(const std::string& root,
+ const std::string& instance,
+ const std::string& type,
+ const std::string& id,
+ const std::string& sensor);
+
// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4