xref: /openbmc/bmcweb/include/watchdog.hpp (revision 9f03894ecf12e0d0ffb0ba7855c256f33f959e44)
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 #pragma once
4 
5 #include "bmcweb_config.h"
6 
7 #include "io_context_singleton.hpp"
8 #include "logging.hpp"
9 
10 #include <systemd/sd-daemon.h>
11 
12 #include <boost/asio/steady_timer.hpp>
13 #include <boost/system/error_code.hpp>
14 
15 #include <chrono>
16 #include <cstdint>
17 #include <functional>
18 #include <ratio>
19 
20 namespace bmcweb
21 {
22 
23 class ServiceWatchdog
24 {
25   public:
26     ServiceWatchdog() : timer(getIoContext())
27     {
28         uint64_t usecondTimeout = 0;
29         if (sd_watchdog_enabled(0, &usecondTimeout) <= 0)
30         {
31             if (BMCWEB_WATCHDOG_TIMEOUT_SECONDS > 0)
32             {
33                 BMCWEB_LOG_WARNING(
34                     "Watchdog timeout was enabled at compile time, but disabled at runtime");
35             }
36             return;
37         }
38         // Pet the watchdog N times faster than required.
39         uint64_t petRatio = 4;
40         watchdogTime = std::chrono::duration<uint64_t, std::micro>(
41             usecondTimeout / petRatio);
42         startTimer();
43     }
44 
45   private:
46     void startTimer()
47     {
48         timer.expires_after(watchdogTime);
49         timer.async_wait(
50             std::bind_front(&ServiceWatchdog::handleTimeout, this));
51     }
52 
53     void handleTimeout(const boost::system::error_code& ec)
54     {
55         if (ec)
56         {
57             BMCWEB_LOG_ERROR("Watchdog timer async_wait failed: {}",
58                              ec.message());
59             return;
60         }
61 
62         int rc = sd_notify(0, "WATCHDOG=1");
63         if (rc < 0)
64         {
65             BMCWEB_LOG_ERROR("sd_notify failed: {}", -rc);
66             return;
67         }
68 
69         startTimer();
70     }
71 
72     boost::asio::steady_timer timer;
73     std::chrono::duration<uint64_t, std::micro> watchdogTime{};
74 };
75 
76 } // namespace bmcweb
77