Skip to content

Commit

Permalink
Handle recursive aux builds without deadlock
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Sep 8, 2024
1 parent 721ed1b commit 263849d
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

* aux builds don't hang anymore if they are recursively depending on themselves

### Changed

* Basic tests now work even without the `rustc` cargo feature

### Removed

## [0.26.0] - 2024-09-07
Expand Down
42 changes: 39 additions & 3 deletions src/build_manager.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Auxiliary and dependency builder. Extendable to custom builds.
use std::{
cell::RefCell,
collections::{hash_map::Entry, HashMap},
ffi::OsString,
sync::{Arc, OnceLock, RwLock},
Expand Down Expand Up @@ -84,6 +85,39 @@ impl BuildManager {
});
}
let mut lock = self.cache.write().unwrap();

thread_local! {
static STACK: RefCell<Vec<String>> = RefCell::new(vec![]);
}
STACK.with_borrow_mut(|stack| {
if stack.contains(&description) {
Err(Errored {
command: format!("{description:?}"),
errors: vec![],
stderr: b"recursive build".to_vec(),
stdout: vec![],
})
} else {
stack.push(description.clone());
Ok(())
}
})?;
struct Handle(Arc<OnceLock<Result<Vec<OsString>, ()>>>, String);

impl std::ops::Deref for Handle {
type Target = OnceLock<Result<Vec<OsString>, ()>>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl Drop for Handle {
fn drop(&mut self) {
STACK.with_borrow_mut(|stack| assert_eq!(stack.pop().unwrap(), self.1))
}
}

let once = match lock.entry(description) {
Entry::Occupied(entry) => {
if let Some(res) = entry.get().get() {
Expand All @@ -94,12 +128,14 @@ impl BuildManager {
stdout: vec![],
});
}
entry.get().clone()

Handle(entry.get().clone(), entry.key().clone())
}
Entry::Vacant(entry) => {
let once = Arc::new(OnceLock::new());
entry.insert(once.clone());
once
let handle = Handle(once.clone(), entry.key().clone());
entry.insert(once);
handle
}
};
drop(lock);
Expand Down
28 changes: 27 additions & 1 deletion tests/integrations/basic-fail/Cargo.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,8 @@ tests/actual_tests_bless/no_test.rs ... FAILED
tests/actual_tests_bless/non_top_level_configs.rs ... FAILED
tests/actual_tests_bless/pass.rs ... ok
tests/actual_tests_bless/pass_with_annotation.rs ... FAILED
Building aux file tests/actual_tests_bless/auxiliary/recursive.rs ... FAILED
tests/actual_tests_bless/recursive_aux_build.rs ... FAILED
tests/actual_tests_bless/revised_revision.rs ... FAILED
tests/actual_tests_bless/revisioned_executable.rs (revision `run`) ... ok
tests/actual_tests_bless/revisioned_executable.rs (revision `panic`) ... ok
Expand Down Expand Up @@ -767,6 +769,29 @@ full stdout:



FAILED TEST: tests/actual_tests_bless/recursive_aux_build.rs
command: "$CMD"

error: aux build failed
--> tests/actual_tests_bless/recursive_aux_build.rs:1:16
|
1 | //@ aux-build: recursive.rs
| ^^^^^^^^^^^^ tests/actual_tests_bless/recursive_aux_build.rs
|
error: aux build failed
--> tests/actual_tests_bless/auxiliary/recursive.rs:1:16
|
1 | //@ aux-build: recursive.rs
| ^^^^^^^^^^^^ tests/actual_tests_bless/auxiliary/recursive.rs
|


full stderr:
recursive build
full stdout:



FAILED TEST: tests/actual_tests_bless/revised_revision.rs
command: parse comments

Expand Down Expand Up @@ -1066,6 +1091,7 @@ FAILURES:
tests/actual_tests_bless/no_test.rs
tests/actual_tests_bless/non_top_level_configs.rs
tests/actual_tests_bless/pass_with_annotation.rs
tests/actual_tests_bless/recursive_aux_build.rs
tests/actual_tests_bless/revised_revision.rs
tests/actual_tests_bless/revisioned_executable.rs (revision panic.run)
tests/actual_tests_bless/revisioned_executable_panic.rs (revision run.run)
Expand All @@ -1078,7 +1104,7 @@ FAILURES:
tests/actual_tests_bless/unknown_revision2.rs
tests/actual_tests_bless/wrong_diagnostic_code.rs

test result: FAIL. 23 failed; 24 passed; 3 ignored
test result: FAIL. 24 failed; 24 passed; 3 ignored

Building dependencies ... ok
tests/actual_tests_bless_yolo/revisions_bad.rs (revision `foo`) ... ok
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//@ aux-build: recursive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//@ aux-build: recursive.rs

0 comments on commit 263849d

Please sign in to comment.