#[cfg(target_os = "linux")]
pub(crate) struct StderrRedirectGuard {
saved_stderr: std::os::fd::RawFd,
}
#[cfg(target_os = "linux")]
impl StderrRedirectGuard {
pub(crate) fn new() -> Option<Self> {
use std::fs::OpenOptions;
use std::os::fd::AsRawFd;
let devnull = OpenOptions::new().write(true).open("/dev/null").ok()?;
unsafe {
let saved_stderr = libc::dup(libc::STDERR_FILENO);
if saved_stderr < 0 {
return None;
}
if libc::dup2(devnull.as_raw_fd(), libc::STDERR_FILENO) < 0 {
libc::close(saved_stderr);
return None;
}
Some(Self { saved_stderr })
}
}
}
#[cfg(target_os = "linux")]
impl Drop for StderrRedirectGuard {
fn drop(&mut self) {
unsafe {
libc::dup2(self.saved_stderr, libc::STDERR_FILENO);
libc::close(self.saved_stderr);
}
}
}
#[cfg(target_os = "linux")]
pub(crate) fn silence_alsa<T>(f: impl FnOnce() -> T) -> T {
use std::sync::{Mutex, OnceLock};
static STDERR_REDIRECT_LOCK: OnceLock<Mutex<()>> = OnceLock::new();
let lock = STDERR_REDIRECT_LOCK.get_or_init(|| Mutex::new(()));
let _lock_guard = lock.lock().unwrap_or_else(|p| p.into_inner());
let Some(_redirect_guard) = StderrRedirectGuard::new() else {
return f();
};
f()
}
#[cfg(not(target_os = "linux"))]
pub(crate) fn silence_alsa<T>(f: impl FnOnce() -> T) -> T {
f()
}