Skip to content

Commit

Permalink
fix(cpu_timer): minimize unsoundness for ffi routines
Browse files Browse the repository at this point in the history
(cherry picked from commit 4093ba5)
  • Loading branch information
nyannyacha committed Jan 10, 2024
1 parent 65ef283 commit 3a11551
Showing 1 changed file with 41 additions and 29 deletions.
70 changes: 41 additions & 29 deletions crates/cpu_timer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#![allow(clippy::arc_with_non_send_sync)]

pub mod timerid;

use std::{cell::RefCell, sync::Arc};
use std::sync::Arc;

#[cfg(target_os = "linux")]
use crate::timerid::TimerId;
Expand All @@ -12,28 +10,35 @@ use anyhow::bail;
use anyhow::Error;
use log::debug;
use nix::sys::signal;
use tokio::sync::mpsc;
use tokio::sync::{mpsc, Mutex};

#[repr(C)]
#[derive(Clone)]
pub struct CPUAlarmVal {
pub cpu_alarms_tx: mpsc::UnboundedSender<()>,
}

#[cfg(target_os = "linux")]
#[derive(Clone)]
pub struct CPUTimer {
_timerid: Arc<TimerId>,
_cpu_alarm_val: Arc<RefCell<CPUAlarmVal>>,
struct CPUTimerVal {
id: TimerId,
initial_expiry: u64,
interval: u64,
}

#[cfg(target_os = "linux")]
unsafe impl Send for CPUTimerVal {}

#[cfg(target_os = "linux")]
#[derive(Clone)]
pub struct CPUTimer {
_timer: Arc<Mutex<CPUTimerVal>>,
_cpu_alarm_val: Arc<CPUAlarmVal>,
}

#[cfg(not(target_os = "linux"))]
#[derive(Clone)]
pub struct CPUTimer {}

unsafe impl Send for CPUTimer {}

impl CPUTimer {
#[cfg(target_os = "linux")]
pub fn start(
Expand All @@ -42,14 +47,14 @@ impl CPUTimer {
cpu_alarm_val: CPUAlarmVal,
) -> Result<Self, Error> {
let mut timerid = TimerId(std::ptr::null_mut());
let cpu_alarm_val = Arc::new(RefCell::new(cpu_alarm_val));
let cpu_alarm_ptr = cpu_alarm_val.as_ptr();
let sival_ptr: *mut libc::c_void = cpu_alarm_ptr as *mut libc::c_void;

let mut sigev: libc::sigevent = unsafe { std::mem::zeroed() };
let cpu_alarm_val = Arc::new(cpu_alarm_val);

sigev.sigev_notify = libc::SIGEV_SIGNAL;
sigev.sigev_signo = libc::SIGALRM;
sigev.sigev_value = libc::sigval { sival_ptr };
sigev.sigev_value = libc::sigval {
sival_ptr: Arc::as_ptr(&cpu_alarm_val) as *mut _,
};

if unsafe {
// creates a new per-thread timer
Expand All @@ -64,10 +69,12 @@ impl CPUTimer {
}

let this = Self {
_timerid: Arc::new(timerid),
_timer: Arc::new(Mutex::new(CPUTimerVal {
id: timerid,
initial_expiry,
interval,
})),
_cpu_alarm_val: cpu_alarm_val,
initial_expiry,
interval,
};

Ok({
Expand All @@ -78,10 +85,14 @@ impl CPUTimer {

#[cfg(target_os = "linux")]
pub fn reset(&self) -> Result<(), Error> {
let initial_expiry_secs = self.initial_expiry / 1000;
let initial_expiry_msecs = self.initial_expiry % 1000;
let interval_secs = self.interval / 1000;
let interval_msecs = self.interval % 1000;
use anyhow::Context;

let timer = self._timer.try_lock().context("failed to get the lock")?;

let initial_expiry_secs = timer.initial_expiry / 1000;
let initial_expiry_msecs = timer.initial_expiry % 1000;
let interval_secs = timer.interval / 1000;
let interval_msecs = timer.interval % 1000;
let mut tmspec: libc::itimerspec = unsafe { std::mem::zeroed() };

tmspec.it_value.tv_sec = initial_expiry_secs as i64;
Expand All @@ -91,7 +102,7 @@ impl CPUTimer {

if unsafe {
// start the timer with an expiry
libc::timer_settime(self._timerid.0, 0, &tmspec, std::ptr::null_mut())
libc::timer_settime(timer.id.0, 0, &tmspec, std::ptr::null_mut())
} < 0
{
bail!(std::io::Error::last_os_error())
Expand All @@ -113,13 +124,14 @@ impl CPUTimer {
}

extern "C" fn sigalrm_handler(_: libc::c_int, info: *mut libc::siginfo_t, _: *mut libc::c_void) {
let cpu_alarms_tx: mpsc::UnboundedSender<()>;
unsafe {
let cpu_alarms_tx = unsafe {
let sival = (*info).si_value();
let boxed_state = Box::from_raw(sival.sival_ptr as *mut CPUAlarmVal);
cpu_alarms_tx = boxed_state.cpu_alarms_tx.clone();
std::mem::forget(boxed_state);
}
let val = Arc::from_raw(sival.sival_ptr as *const CPUAlarmVal);
let sig = val.cpu_alarms_tx.clone();

std::mem::forget(val);
sig
};

if cpu_alarms_tx.send(()).is_err() {
debug!("failed to send cpu alarm to the provided channel");
Expand Down

0 comments on commit 3a11551

Please sign in to comment.