use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use supermachine::{Image, VmConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let snap = format!(
"{}/.local/supermachine-snapshots/nginx_1v",
std::env::var("HOME")?
);
let port: u16 = std::env::var("PORT")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(8081);
let image = Image::from_snapshot(&snap)?;
let vm = image.start(&VmConfig::new())?;
let _fwd = vm.expose_tcp(port, 80)?;
println!("listening on http://127.0.0.1:{port}/ (Ctrl-C to stop)");
let stop = Arc::new(AtomicBool::new(false));
let s = stop.clone();
ctrlc_handler(move || s.store(true, Ordering::SeqCst));
while !stop.load(Ordering::SeqCst) {
std::thread::sleep(std::time::Duration::from_millis(200));
}
vm.stop()?;
Ok(())
}
fn ctrlc_handler<F: FnMut() + Send + 'static>(mut cb: F) {
unsafe {
let mut sa: libc::sigaction = std::mem::zeroed();
sa.sa_sigaction = sigint_handler as usize;
libc::sigemptyset(&mut sa.sa_mask);
sa.sa_flags = libc::SA_RESTART;
libc::sigaction(libc::SIGINT, &sa, std::ptr::null_mut());
}
std::thread::spawn(move || loop {
let n = SIGINT_COUNT.load(Ordering::SeqCst);
if n > 0 {
cb();
return;
}
std::thread::sleep(std::time::Duration::from_millis(100));
});
}
static SIGINT_COUNT: std::sync::atomic::AtomicUsize =
std::sync::atomic::AtomicUsize::new(0);
extern "C" fn sigint_handler(_sig: libc::c_int) {
SIGINT_COUNT.fetch_add(1, Ordering::SeqCst);
}