pub struct Watchdog { /* private fields */ }
Expand description
Structure representing the watchdog.
When opening the file representing the watchdog driver in the Linux filesystem, the watchdog activates and needs to be pinged to avoid a system reset.
Implementations§
Source§impl Watchdog
impl Watchdog
Sourcepub fn new() -> Result<Self, Error>
pub fn new() -> Result<Self, Error>
Instantiates the default watchdog.
The creation of the instance causes the activation of the watchdog.
Since this involves opening the ‘/dev/watchdog’ file representing the driver,
the user must have the appropriate read/write permissions to access it. If this is not the case, an error will be returned.
After this call, the only way to prevent a system reset is to periodically call keep_alive()
before the configured timeout elapses (see get_timeout()
and get_time_left()
).
If the ‘magic close’ feature is supported (see is_option_supported()
to verify),
it is possible to deactivate the watchdog by calling magic_close()
.
Once the watchdog is active, an alternative way to keep the system alive is to call
start_automatic_keep_alive()
just once.
See the documentation of each method for more information.
Sourcepub fn new_by_id(id: u8) -> Result<Self, Error>
pub fn new_by_id(id: u8) -> Result<Self, Error>
Instantiates a specific watchdog with a numeric identifier.
Unlike new()
, it creates a watchdog instance by opening the
‘/dev/watchdogID’ file (e.g. ‘/dev/watchdog0’, ‘/dev/watchdog37’, etc.).
The ID passed as parameter indicates the number suffix of the watchdog file.
As with new()
, The creation of the instance causes the activation of the watchdog.
See new()
for more information.
Sourcepub fn keep_alive(&mut self) -> Result<(), Errno>
pub fn keep_alive(&mut self) -> Result<(), Errno>
Keeps the system alive.
The watchdog automatically triggers a system reset if not pinged for a preconfigured timeout
(see get_timeout()
and get_time_left()
).
In order to prevent this, this method must be called periodically before the timeout expires.
Sourcepub fn start_automatic_keep_alive(
watchdog_mut_arc: Arc<Mutex<Self>>,
) -> JoinHandle<()>
pub fn start_automatic_keep_alive( watchdog_mut_arc: Arc<Mutex<Self>>, ) -> JoinHandle<()>
Starts automatically keeping the system alive.
In a normal operation, the user should periodically call keep_alive()
to prevent the watchdog from triggering a system reset.
When calling this, a separate thread is spawned that takes care of pinging the watchdog once every second.
The ‘auto keep alive’ thread is signaled to be closed as soon as the watchdog instance is released from memory.
This means that without triggering the magic_close()
feature, releasing the watchdog will still cause a system reset after the timeout period.
Disclaimer: this feature should only be considered if the user is sure that their use case will not defeat the purpose of having a watchdog in the first place. As an example, if the main thread malfunctions but the ‘auto keep alive’ thread is able to keep running, the watchdog will still be pinged normally and no reset will take place. This is clearly an undersirable behaviour, so particular caution must be taken when using this.
§Panics
This method can panic in case the passed mutex is poisoned. The same also can happen inside the spawned thread.
§Examples
use watchdog_device::Watchdog;
use nix::errno::Errno;
use std::sync::{Arc, Mutex};
let mut wd = Watchdog::new()?;
let wd_mutex_arc: Arc<Mutex<Watchdog>> = Arc::new(Mutex::new(wd));
let handle = Watchdog::start_automatic_keep_alive(wd_mutex_arc.clone());
loop{
do_something();
}
handle.join().expect("Error joining thread.");
Sourcepub fn get_firmware_version(&self) -> Result<u32, Errno>
pub fn get_firmware_version(&self) -> Result<u32, Errno>
Returns the version of the firmware.
If available, this returns the firmware version of the card.
§Examples
use watchdog_device::Watchdog;
use nix::errno::Errno;
use log::{info, error};
let mut wd = Watchdog::new()?;
let result = wd.get_firmware_version();
match result{
Ok(fw_ver) => info!("Firmware version:{}", fw_ver),
Err(errno) => {
error!("error:{}", errno);
},
}
Sourcepub fn get_status(&self, option: &OptionFlags) -> Result<bool, Errno>
pub fn get_status(&self, option: &OptionFlags) -> Result<bool, Errno>
Returns the status of an option.
For any supported option (see is_option_supported()
), this returns its related current status.
See also get_boot_status()
to retrieve the status at the last reboot.
Note that not all devices support these two calls; some only support one of them.
§Examples
use watchdog_device::{Watchdog, OptionFlags};
use nix::errno::Errno;
use log::info;
let mut wd = Watchdog::new()?;
let option = OptionFlags::Overheat;
if wd.is_option_supported(&option).unwrap(){
info!("Overheat:{}", wd.get_status(&option).unwrap());
}
Sourcepub fn get_boot_status(&self, option: &OptionFlags) -> Result<bool, Errno>
pub fn get_boot_status(&self, option: &OptionFlags) -> Result<bool, Errno>
Returns the status of an option at the last reboot.
For any supported option (see is_option_supported()
), this returns its related status at the last reboot.
See also get_status()
to retrieve the current status.
Note that not all devices support these two calls; some only support one of them.
§Examples
use watchdog_device::{Watchdog, OptionFlags};
use nix::errno::Errno;
use log::info;
let mut wd = Watchdog::new()?;
let option = OptionFlags::Overheat;
if wd.is_option_supported(&option).unwrap(){
info!("Overheat at last boot:{}", wd.get_boot_status(&option).unwrap());
}
Sourcepub fn is_option_supported(&self, option: &OptionFlags) -> Result<bool, Errno>
pub fn is_option_supported(&self, option: &OptionFlags) -> Result<bool, Errno>
Tells if an option is supported.
From the Linux Kernel Watchdog API documentation:
All watchdog drivers are required return more information about the system, some do temperature, fan and power level monitoring, some can tell you the reason for the last reboot of the system.
This call is available to ask what the device can do. See OptionFlags
for a description of each option.
§Examples
use watchdog_device::{Watchdog, OptionFlags};
use nix::errno::Errno;
use log::info;
let mut wd = Watchdog::new()?;
info!("FanFault option support:{}", wd.is_option_supported(&OptionFlags::FanFault).unwrap());
Sourcepub fn get_driver_identity(&self) -> Result<String, Errno>
pub fn get_driver_identity(&self) -> Result<String, Errno>
Returns the watchdog driver identifier.
This returns a String containing the identifier for the watchdog driver.
§Examples
use watchdog_device::Watchdog;
use nix::errno::Errno;
use log::info;
let mut wd = Watchdog::new()?;
info!("Driver ID:{}", wd.get_driver_identity().unwrap());
Sourcepub fn get_timeout(&self) -> Result<i32, Errno>
pub fn get_timeout(&self) -> Result<i32, Errno>
Returns the configured timeout.
This is used to know the number of seconds the watchdog will wait before triggering a reset.
§Examples
use watchdog_device::Watchdog;
use nix::errno::Errno;
use log::info;
let mut wd = Watchdog::new()?;
info!("Current configured timeout:{}", wd.get_timeout().unwrap());
Sourcepub fn get_pretimeout(&self) -> Result<i32, Errno>
pub fn get_pretimeout(&self) -> Result<i32, Errno>
Returns the configured pre-timeout, if suppported.
From the Linux Kernel Watchdog API documentation:
Some watchdog timers can be set to have a trigger go off before the actual time they will reset the system. This can be done with an NMI, interrupt, or other mechanism. This allows Linux to record useful information (like panic information and kernel coredumps) before it resets.
Note that the pretimeout is the number of seconds before the time when the timeout will go off. It is not the number of seconds until the pretimeout. So, for instance, if you set the timeout to 60 seconds and the pretimeout to 10 seconds, the pretimeout will go off in 50 seconds. Setting a pretimeout to zero disables it.
Not all watchdog drivers will support a pretimeout.
§Examples
use watchdog_device::{Watchdog, OptionFlags};
use nix::errno::Errno;
use log::info;
let mut wd = Watchdog::new()?;
if wd.is_option_supported(&OptionFlags::PreTimeout).unwrap(){
info!("Current configured pre-timeout:{}", wd.get_timeout().unwrap());
}
Sourcepub fn get_time_left(&self) -> Result<i32, Errno>
pub fn get_time_left(&self) -> Result<i32, Errno>
Returns the time left before reset.
Some watchdog drivers have the ability to report the remaining time before the system will reboot. The returned value is the number of seconds left at the moment of the call.
§Examples
use watchdog_device::Watchdog;
use nix::errno::Errno;
use log::info;
let mut wd = Watchdog::new()?;
info!("Number of seconds left:{}", wd.get_time_left().unwrap());
Sourcepub fn get_temp(&self) -> Result<i32, Errno>
pub fn get_temp(&self) -> Result<i32, Errno>
Returns the current temperature.
Some drivers can measure the temperature. The returned value is the temperature in degrees fahrenheit.
§Examples
use watchdog_device::Watchdog;
use nix::errno::Errno;
use log::info;
let mut wd = Watchdog::new()?;
info!("Current temperature:{}F", wd.get_temp().unwrap());
Sourcepub fn set_timeout(&self, timeout: i32) -> Result<i32, Errno>
pub fn set_timeout(&self, timeout: i32) -> Result<i32, Errno>
Configures the timeout, if supported.
For some drivers it is possible to modify the watchdog timeout on the fly by calling this method.
It is possible to verify the support for this feature by calling is_option_supported()
with OptionFlags::SetTimeout
as an argument.
The argument is an integer representing the timeout in seconds. If the value is unsupported, the function will return an EINVAL error.
The driver returns the real timeout used in the same variable, and this timeout might differ from the requested one due to limitation of the hardware
§Examples
use watchdog_device::{Watchdog, OptionFlags};
use nix::errno::Errno;
use log::info;
let mut wd = Watchdog::new()?;
if wd.is_option_supported(&OptionFlags::SetTimeout).unwrap(){
let requested_timeout = 14;
let returned_configured_timeout = wd.set_timeout(requested_timeout).unwrap();
info!("requested timeout:{} - returned value:{}", requested_timeout, returned_configured_timeout);
}
Sourcepub fn set_pretimeout(&self, pretimeout: i32) -> Result<i32, Errno>
pub fn set_pretimeout(&self, pretimeout: i32) -> Result<i32, Errno>
Configures the pre-timeout, if suppported.
From the Linux Kernel Watchdog API documentation:
Some watchdog timers can be set to have a trigger go off before the actual time they will reset the system. This can be done with an NMI, interrupt, or other mechanism. This allows Linux to record useful information (like panic information and kernel coredumps) before it resets.
Note that the pretimeout is the number of seconds before the time when the timeout will go off. It is not the number of seconds until the pretimeout. So, for instance, if you set the timeout to 60 seconds and the pretimeout to 10 seconds, the pretimeout will go off in 50 seconds. Setting a pretimeout to zero disables it.
The argument is an integer representing the timeout in seconds. The driver returns the real timeout used in the same variable, and this timeout might differ from the requested one due to limitation of the hardware.
Not all watchdog drivers will support a pretimeout.
§Examples
use watchdog_device::{Watchdog, OptionFlags};
use nix::errno::Errno;
use log::info;
let mut wd = Watchdog::new()?;
if wd.is_option_supported(&OptionFlags::PreTimeout).unwrap(){
let requested_timeout = 27;
let returned_configured_timeout = wd.set_pretimeout(requested_timeout).unwrap();
info!("requested pre-timeout:{} - returned value:{}", requested_timeout, returned_configured_timeout);
}
Sourcepub fn set_option(&self, option: &SetOptionFlags) -> Result<(), Errno>
pub fn set_option(&self, option: &SetOptionFlags) -> Result<(), Errno>
Sets a watchdog operation.
This can be used to control some aspects of the card operation, if supported.
The SetOptionFlags
enum lists all the operations that is possible to trigger.
Sourcepub fn magic_close(&mut self) -> Result<()>
pub fn magic_close(&mut self) -> Result<()>
Disables the watchdog, if supported.
If a driver supports “Magic Close”, the driver will not disable the watchdog unless magic_close()
is called
just before releasing the Watchdog
instance.
If the user closes the watchdog without calling this, the driver will assume that the program (and userspace in general) died,
and will stop pinging the watchdog without disabling it first. This will then cause a reboot if the watchdog is not re-opened in sufficient time.
When the device is closed, the watchdog is disabled, unless the “Magic Close” feature is supported (see below). This is not always such a good idea, since if there is a bug in the watchdog daemon and it crashes the system will not reboot. Because of this, some of the drivers support the configuration option “Disable watchdog shutdown on close”, CONFIG_WATCHDOG_NOWAYOUT. If it is set to Y when compiling the kernel, there is no way of disabling the watchdog once it has been started. So, if the watchdog daemon crashes, the system will reboot after the timeout has passed. Watchdog devices also usually support the nowayout module parameter so that this option can be controlled at runtime.
§Examples
use watchdog_device::{Watchdog, OptionFlags};
use nix::errno::Errno;
let mut wd = Watchdog::new()?;
while keep_running{
do_something();
if let Err(e) = wd.keep_alive(){
println!("Error {}", e);
}
}
if wd.is_option_supported(&OptionFlags::MagicClose).unwrap(){
wd.magic_close()?;
}