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