| // SPDX-License-Identifier: Apache-2.0 |
| // SPDX-FileCopyrightText: Copyright OpenBMC Authors |
| #pragma once |
| |
| #include "bmcweb_config.h" |
| |
| #include "io_context_singleton.hpp" |
| #include "logging.hpp" |
| |
| #include <systemd/sd-daemon.h> |
| |
| #include <boost/asio/steady_timer.hpp> |
| #include <boost/system/error_code.hpp> |
| |
| #include <chrono> |
| #include <cstdint> |
| #include <functional> |
| #include <ratio> |
| |
| namespace bmcweb |
| { |
| |
| class ServiceWatchdog |
| { |
| public: |
| ServiceWatchdog() : timer(getIoContext()) |
| { |
| uint64_t usecondTimeout = 0; |
| if (sd_watchdog_enabled(0, &usecondTimeout) <= 0) |
| { |
| if (BMCWEB_WATCHDOG_TIMEOUT_SECONDS > 0) |
| { |
| BMCWEB_LOG_WARNING( |
| "Watchdog timeout was enabled at compile time, but disabled at runtime"); |
| } |
| return; |
| } |
| // Pet the watchdog N times faster than required. |
| uint64_t petRatio = 4; |
| watchdogTime = std::chrono::duration<uint64_t, std::micro>( |
| usecondTimeout / petRatio); |
| startTimer(); |
| } |
| |
| private: |
| void startTimer() |
| { |
| timer.expires_after(watchdogTime); |
| timer.async_wait( |
| std::bind_front(&ServiceWatchdog::handleTimeout, this)); |
| } |
| |
| void handleTimeout(const boost::system::error_code& ec) |
| { |
| if (ec) |
| { |
| BMCWEB_LOG_ERROR("Watchdog timer async_wait failed: {}", |
| ec.message()); |
| return; |
| } |
| |
| int rc = sd_notify(0, "WATCHDOG=1"); |
| if (rc < 0) |
| { |
| BMCWEB_LOG_ERROR("sd_notify failed: {}", -rc); |
| return; |
| } |
| |
| startTimer(); |
| } |
| |
| boost::asio::steady_timer timer; |
| std::chrono::duration<uint64_t, std::micro> watchdogTime{}; |
| }; |
| |
| } // namespace bmcweb |