use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;
use super::{ChildGuard, ProcessError, ProcessSpec, spawn};
pub(crate) enum CancellableOutcome {
Completed,
Cancelled,
}
pub(crate) fn run_cancellable(
specification: &ProcessSpec,
stopping: &AtomicBool,
) -> Result<CancellableOutcome, ProcessError> {
if stopping.load(Ordering::SeqCst) {
return Ok(CancellableOutcome::Cancelled);
}
let mut child = ChildGuard::new(spawn(specification)?, "backend build");
loop {
if stopping.load(Ordering::SeqCst) {
child.terminate()?;
return Ok(CancellableOutcome::Cancelled);
}
if let Some(status) = child.try_wait()? {
return if status.success() {
Ok(CancellableOutcome::Completed)
} else {
Err(ProcessError::Failed {
program: specification.program().to_string_lossy().into_owned(),
directory: specification.directory().to_path_buf(),
status,
})
};
}
thread::sleep(Duration::from_millis(25));
}
}