#![allow(unsafe_code)]
use tracing::{debug, error};
use crate::error::{Result, StutterError};
static WARNED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
fn handle_errno(pid: u32, errno: i32, action: &str) -> Result<()> {
if errno == libc::ESRCH {
debug!("pid {pid} not found (ESRCH), skipping");
return Ok(());
}
if (errno == libc::EPERM || errno == libc::EACCES)
&& !WARNED.swap(true, std::sync::atomic::Ordering::Relaxed)
{
error!("permission denied when {action} priority for pid {pid}. ensure CAP_SYS_NICE or root");
}
Err(StutterError::Priority { pid, errno })
}
pub fn set_priority(pid: u32, nice: i32, dry_run: bool) -> Result<()> {
if dry_run {
println!("[stutter] [DRY RUN] would set pid {pid} to nice {nice}");
return Ok(());
}
unsafe { *libc::__errno_location() = 0 };
let ret = unsafe { libc::setpriority(libc::PRIO_PROCESS, pid, nice) };
if ret == -1 {
let errno = unsafe { *libc::__errno_location() };
return handle_errno(pid, errno, "setting");
}
Ok(())
}