watchdog: Handle systemd StartUnit errors
Currently, if systemd returns an error upon trying to StartUnit in the
timeout of the watchdog the entire daemon will crash.
Sep 28 22:59:09 phosphor-watchdog[2462]: Timer Expired
Sep 28 22:59:09 phosphor-watchdog[2462]: watchdog: Timed out
Sep 28 22:59:09 phosphor-watchdog[2462]: terminate called after throwing an instance of 'sdbusplus::exception::SdBusError'
Sep 28 22:59:09 phosphor-watchdog[2462]: what(): sd_bus_call noreply: org.freedesktop.DBus.Error.InvalidArgs: Unit ho
st-watchdog-reset.service is not loaded properly: Invalid argument.
This patch fixes the behavior so we get something more like:
Oct 04 07:12:14 phosphor-watchdog[10897]: watchdog: Timed out
Oct 04 07:12:14 phosphor-watchdog[10897]: watchdog: Failed to start unit
Oct 04 07:12:16 phosphor-watchdog[10897]: watchdog: disabled
Tested:
Ran with a bogus systemd target which used to throw errors which are
now correctly handled without crashing.
Change-Id: I4cf6ffded789e49d2329439165927cc227e2e79e
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/watchdog.cpp b/watchdog.cpp
index 9301fb0..92134ff 100644
--- a/watchdog.cpp
+++ b/watchdog.cpp
@@ -1,7 +1,11 @@
#include "watchdog.hpp"
#include <chrono>
+#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/log.hpp>
+#include <sdbusplus/exception.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+
namespace phosphor
{
namespace watchdog
@@ -10,6 +14,9 @@
using namespace std::chrono_literals;
using namespace phosphor::logging;
+using sdbusplus::exception::SdBusError;
+using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+
// systemd service to kick start a target.
constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
@@ -120,15 +127,26 @@
}
else
{
- auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
- SYSTEMD_INTERFACE, "StartUnit");
- method.append(target->second);
- method.append("replace");
-
log<level::INFO>("watchdog: Timed out",
entry("ACTION=%s", convertForMessage(action).c_str()),
entry("TARGET=%s", target->second.c_str()));
- bus.call_noreply(method);
+
+ try
+ {
+ auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
+ SYSTEMD_INTERFACE, "StartUnit");
+ method.append(target->second);
+ method.append("replace");
+
+ bus.call_noreply(method);
+ }
+ catch (const SdBusError& e)
+ {
+ log<level::ERR>("watchdog: Failed to start unit",
+ entry("TARGET=%s", target->second.c_str()),
+ entry("ERROR=%s", e.what()));
+ commit<InternalFailure>();
+ }
}
tryFallbackOrDisable();