Repository: firecracker-microvm/firecracker
File: src/utils/src/time.rs (Rust)

Code before:
    }

    /// Arm the timer to be triggered after `duration` and then
    /// at optional `interval`
    pub fn arm(&mut self, duration: Duration, interval: Option<Duration>) {
        #[allow(clippy::cast_possible_wrap)]
        let spec = libc::itimerspec {
            it_value: libc::timespec {
                tv_sec: duration.as_secs() as i64,
                tv_nsec: duration.subsec_nanos() as i64,
            },
            it_interval: if let Some(interval) = interval {
                libc::timespec {
                    tv_sec: interval.as_secs() as i64,
                    tv_nsec: interval.subsec_nanos() as i64,
                }
            } else {
                libc::timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                }
            },
        };
        // SAFETY: Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { libc::timerfd_settime(self.as_raw_fd(), 0, &spec, ptr::null_mut()) };
        assert!(0 <= ret, "TimerFd arm failed: {ret}");
    }

    /// Read the value from the timerfd. Since it is always created with NONBLOCK flag,
    /// this function does not block.
    pub fn read(&mut self) -> u64 {
        let mut buf = [0u8; size_of::<u64>()];
        match self.0.read(buf.as_mut_slice()) {
            Ok(_) => u64::from_ne_bytes(buf),
            Err(inner) if inner.kind() == ErrorKind::WouldBlock => 0,
            Err(err) => panic!("TimerFd read failed: {err}"),
        }
    }

    /// Tell if the timer is currently armed.
    pub fn is_armed(&self) -> bool {
        // SAFETY: Zero init of a PDO type.
        let mut spec: libc::itimerspec = unsafe { std::mem::zeroed() };
        // SAFETY: Safe because timerfd_gettime is trusted to only modify `spec`.
        let ret = unsafe { libc::timerfd_gettime(self.as_raw_fd(), &mut spec) };
        assert!(0 <= ret, "TimerFd arm failed: {ret}");
        spec.it_value.tv_sec != 0 || spec.it_value.tv_nsec != 0
    }
}

impl AsRawFd for TimerFd {

Review comment (suggestion):
the error is always `-1` and `errno` gets set with the actual error. We should probably use `std::io::Error::last_os_error()` to grab it and unwrap it for a nice print.

(same for the other syscalls)

Code after:
            std::io::Error::last_os_error()
        );
        // SAFETY: we just created valid fd
        TimerFd(unsafe { File::from_raw_fd(fd) })
    }

    /// Arm the timer to be triggered after `duration` and then
    /// at optional `interval`
    pub fn arm(&mut self, duration: Duration, interval: Option<Duration>) {
        #[allow(clippy::cast_possible_wrap)]
        let spec = libc::itimerspec {
            it_value: libc::timespec {
                tv_sec: duration.as_secs() as i64,
                tv_nsec: duration.subsec_nanos() as i64,
            },
            it_interval: if let Some(interval) = interval {
                libc::timespec {
                    tv_sec: interval.as_secs() as i64,
                    tv_nsec: interval.subsec_nanos() as i64,
                }
            } else {
                libc::timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                }
            },
        };
        // SAFETY: Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { libc::timerfd_settime(self.as_raw_fd(), 0, &spec, ptr::null_mut()) };
        assert!(
            0 <= ret,
            "TimerFd arm failed: {:#}",
            std::io::Error::last_os_error()
        );
    }

    /// Read the value from the timerfd. Since it is always created with NONBLOCK flag,
    /// this function does not block.
    pub fn read(&mut self) -> u64 {
        let mut buf = [0u8; size_of::<u64>()];
        match self.0.read(buf.as_mut_slice()) {
            Ok(_) => u64::from_ne_bytes(buf),
            Err(inner) if inner.kind() == ErrorKind::WouldBlock => 0,
            Err(err) => panic!("TimerFd read failed: {err:#}"),
        }
    }

    /// Tell if the timer is currently armed.
    pub fn is_armed(&self) -> bool {
        // SAFETY: Zero init of a PDO type.
        let mut spec: libc::itimerspec = unsafe { std::mem::zeroed() };