gpu: init-marker tests use their own scope counter so parallel device tests cannot join them (#1721)

This commit is contained in:
MarekSpodBiedry
2026-10-14 19:31:57 +02:00
parent 3b4279fc24
commit 6e0880769a
+30 -16
View File
@@ -213,12 +213,12 @@ fn disarm(marker: &std::path::Path, active: &Mutex<u32>) {
}
/// Removes the marker on the way out, a panic included (the process survived).
struct Armed(Option<PathBuf>);
struct Armed<'a>(Option<PathBuf>, &'a Mutex<u32>);
impl Drop for Armed {
impl Drop for Armed<'_> {
fn drop(&mut self) {
if let Some(m) = &self.0 {
disarm(m, &ACTIVE);
disarm(m, self.1);
}
}
}
@@ -227,10 +227,16 @@ impl Drop for Armed {
/// removing the init marker (if one is set).
pub(crate) fn with_marker<T>(what: &str, f: impl FnOnce() -> T) -> T {
let marker = MARKER.lock().unwrap_or_else(|e| e.into_inner()).clone();
with_marker_on(marker, &ACTIVE, what, f)
}
/// [`with_marker`] on an explicit marker path and scope counter (the tests use their own, so that
/// device-creating tests running in parallel cannot join their scopes).
fn with_marker_on<T>(marker: Option<PathBuf>, active: &Mutex<u32>, what: &str, f: impl FnOnce() -> T) -> T {
if let Some(m) = &marker {
arm(m, &ACTIVE, what);
arm(m, active, what);
}
let _armed = Armed(marker);
let _armed = Armed(marker, active);
f()
}
@@ -352,9 +358,6 @@ mod tests {
}
use super::*;
/// The tests that set the process-wide marker take turns.
static GLOBAL: Mutex<()> = Mutex::new(());
#[test]
fn parses_backend_names() {
assert_eq!(parse_backends("dx12"), Some(BackendChoice::Use(Backends::DX12)));
@@ -421,13 +424,12 @@ mod tests {
#[test]
fn init_marker_is_written_during_creation_and_removed_after() {
let _turn = GLOBAL.lock().unwrap_or_else(|e| e.into_inner());
let dir = std::env::temp_dir().join(format!("lc-gpu-marker-{}", std::process::id()));
let m = dir.join("gpu-init.marker");
let _ = std::fs::remove_dir_all(&dir);
set_init_marker(Some(m.clone()));
let seen = with_init_marker(Backends::DX12, || m.exists());
set_init_marker(None);
// a local scope counter: other tests create real devices through the process-wide one
let active = Mutex::new(0);
let seen = with_marker_on(Some(m.clone()), &active, "device creation", || m.exists());
assert!(seen, "the marker exists while the device is created");
assert!(!m.exists(), "and is removed afterwards");
// a marker left behind by a crashed process is reported once; reading it leaves it in place
@@ -440,6 +442,20 @@ mod tests {
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn with_init_marker_writes_the_process_wide_marker() {
let dir = std::env::temp_dir().join(format!("lc-gpu-global-{}", std::process::id()));
let m = dir.join("gpu-init.marker");
let _ = std::fs::remove_dir_all(&dir);
set_init_marker(Some(m.clone()));
let seen = with_init_marker(Backends::DX12, || m.exists());
set_init_marker(None);
// not checked for removal: device-creating tests running in parallel may still hold the file
// (the test above checks removal on its own scope counter)
assert!(seen, "the marker set with set_init_marker exists while the device is created");
let _ = std::fs::remove_dir_all(&dir);
}
/// The window's renderer fallback: forced, remembered, the platform chain, the failed one last.
#[test]
fn window_renderer_fallback_order() {
@@ -505,13 +521,11 @@ mod tests {
#[test]
fn a_panic_inside_the_scope_still_removes_the_marker() {
let _turn = GLOBAL.lock().unwrap_or_else(|e| e.into_inner());
let dir = std::env::temp_dir().join(format!("lc-gpu-panic-{}", std::process::id()));
let m = dir.join("gpu-init.marker");
let _ = std::fs::remove_dir_all(&dir);
set_init_marker(Some(m.clone()));
let r = std::panic::catch_unwind(|| with_marker("kernel compilation", || panic!("compile")));
set_init_marker(None);
let active = Mutex::new(0);
let r = std::panic::catch_unwind(|| with_marker_on(Some(m.clone()), &active, "kernel compilation", || panic!("compile")));
assert!(r.is_err());
assert!(!m.exists(), "the process survived, so nothing is left to report");
let _ = std::fs::remove_dir_all(&dir);