use std::panic::{self, AssertUnwindSafe};
use std::sync::Mutex;
use cubecl::client::ComputeClient;
use cubecl::prelude::*;
use crate::accelerate::Accelerator;
static PROBED: Mutex<Vec<Accelerator>> = Mutex::new(Vec::new());
pub(crate) fn open_client<R: Runtime>(
accelerator: Accelerator,
device: &R::Device,
) -> Option<ComputeClient<R>> {
let mut probed = PROBED.lock().unwrap_or_else(|err| err.into_inner());
let opened = quiet_panics(|| {
let client = R::client(device);
cubecl::future::block_on(client.sync()).map(|()| client)
});
match opened {
Ok(Ok(client)) => Some(client),
Ok(Err(err)) => {
tracing::debug!(err = ?err, "could not use the {accelerator} runtime");
None
},
Err(_) => {
if !probed.contains(&accelerator) {
probed.push(accelerator);
tracing::warn!(
"the {accelerator} backend is enabled but did not start, its driver libraries are probably missing"
);
}
None
},
}
}
fn quiet_panics<T>(f: impl FnOnce() -> T) -> std::thread::Result<T> {
let previous = panic::take_hook();
panic::set_hook(Box::new(|info| tracing::debug!("{info}")));
let out = panic::catch_unwind(AssertUnwindSafe(f));
panic::set_hook(previous);
out
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use super::*;
#[test]
fn a_panic_inside_becomes_an_error() {
let _probed = PROBED.lock().unwrap_or_else(|err| err.into_inner());
assert!(quiet_panics(|| panic!("the backend fell over")).is_err());
assert_eq!(quiet_panics(|| 7).unwrap(), 7);
}
#[test]
fn the_panic_hook_is_restored() {
let _probed = PROBED.lock().unwrap_or_else(|err| err.into_inner());
let marker = Arc::new(AtomicBool::new(false));
let flag = marker.clone();
panic::set_hook(Box::new(move |_| flag.store(true, Ordering::SeqCst)));
let _ = quiet_panics(|| panic!("swallowed by the quiet hook"));
assert!(
!marker.load(Ordering::SeqCst),
"the quiet hook did not replace the installed one",
);
let _ = panic::catch_unwind(|| panic!("seen by the restored hook"));
let restored = marker.load(Ordering::SeqCst);
let _ = panic::take_hook();
assert!(restored, "the probe left its own panic hook installed");
}
}