use std::path::Path;
use std::sync::atomic::{AtomicBool, Ordering};
use crate::stage::Stage;
pub const ENV_STAGE: &str = "FEFF10_WORKER_STAGE";
pub const ENV_DIR: &str = "FEFF10_WORKER_DIR";
static INSTALLED: AtomicBool = AtomicBool::new(false);
pub fn installed() -> bool {
INSTALLED.load(Ordering::Relaxed)
}
pub fn init() {
INSTALLED.store(true, Ordering::Relaxed);
let Some(stage_name) = std::env::var_os(ENV_STAGE) else {
return;
};
let Some(dir) = std::env::var_os(ENV_DIR) else {
eprintln!("feff10 worker: missing {ENV_DIR}");
std::process::exit(64);
};
let Some(stage) = Stage::all()
.iter()
.copied()
.find(|s| s.executable_name() == stage_name)
else {
eprintln!("feff10 worker: unknown stage '{stage_name:?}'");
std::process::exit(64);
};
let code = run_stage(stage, Path::new(&dir));
std::process::exit(code);
}
fn run_stage(stage: Stage, dir: &Path) -> i32 {
if let Err(e) = std::env::set_current_dir(dir) {
eprintln!("feff10 worker: cannot enter '{}': {e}", dir.display());
return 66;
}
let result = std::thread::Builder::new()
.name(format!("feff-{stage}"))
.stack_size(64 * 1024 * 1024)
.spawn(move || unsafe { stage.call_ffi() });
if let Ok(thread) = result
&& thread.join().is_ok()
{
return 0;
}
eprintln!("feff10 worker: stage thread failed");
70
}