wip: starter and reaper works

This commit is contained in:
Suyono 2023-11-21 18:18:26 +11:00
parent 6ba6bc6cda
commit ce9df6364f
4 changed files with 93 additions and 11 deletions

View File

@ -6,5 +6,5 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
nix = {version = "0.27.1", features = ["process"]} nix = {version = "0.27.1", features = ["process", "signal"]}
tokio = { version = "1.34.0", features = ["full"] } tokio = { version = "1.34.0", features = ["full"] }

View File

@ -1,19 +1,42 @@
mod sighandler; mod sighandler;
mod waiter; mod waiter;
mod starter;
use std::error; use std::error;
use tokio::task::{self, JoinHandle}; use tokio::task::JoinSet;
use tokio::sync::watch; use tokio::sync::watch;
pub async fn start() -> Result<(), Box<dyn error::Error>> { pub async fn start() -> Result<(), Box<dyn error::Error>> {
let (tx, mut _rx) = watch::channel::<i32>(1); let (tx, mut _rx) = watch::channel::<i32>(1);
let sig_handler_fn: JoinHandle<Result<(), Box<dyn error::Error + Send + Sync>>> = task::spawn(async move { let mut set: JoinSet<Result<(), Box<dyn error::Error + Send + Sync>>> = JoinSet::new();
set.spawn(async move {
sighandler::sighandler(tx).await sighandler::sighandler(tx).await
}); });
if let Err(v) = sig_handler_fn.await? { //TODO: start the process starter
return Err(v as Box<dyn error::Error>) starter::start_process(&mut set);
//TODO: spawn_blocking for waiter
set.spawn_blocking(move || {
waiter::wait_all();
Ok(())
});
//TODO: we can't just return error when we got an error from a task
while let Some(res) = set.join_next().await {
match res {
Ok(v) => {
if let Err(ev) = v {
dbg!(&ev);
return Err(ev as Box<dyn error::Error>);
}
},
Err(e) => {
dbg!(&e);
return Err(e.into());
},
}
} }
Ok(()) Ok(())

View File

@ -0,0 +1,36 @@
use tokio::task::JoinSet;
use tokio::process::Command;
use std::error;
pub fn start_process(ts: &mut JoinSet<Result<(), Box<dyn error::Error + Send + Sync>>>) {
for _j in 0..5 {
ts.spawn(async move {
for _i in 0..5 {
let mut child = Command::new("sleep").arg("1")
.spawn()
.expect("failed to spawn");
match child.wait().await {
Ok(status) => {
println!("starter: sleep exited: {}", status);
},
Err(e) => {
if let Some(eos) = e.raw_os_error() {
if eos != nix::Error::ECHILD as i32 {
return Err(e.into());
}
} else {
return Err(e.into());
}
},
}
// let status = child.wait().await?;
// println!("starter: sleep exited: {}", status);
}
println!("starter: task completed");
Ok(())
});
}
println!("starter: spawning completed");
}

View File

@ -1,10 +1,33 @@
use nix::sys::wait; use nix::errno::Errno;
use nix::sys::wait::{self, WaitStatus};
use nix::unistd::Pid; use nix::unistd::Pid;
#[allow(dead_code)] pub fn wait_all() {
fn wait_all() { 'wait: loop {
match wait::waitpid(Pid::from_raw(-1), Some(wait::WaitPidFlag::WNOHANG)) { match wait::waitpid(Pid::from_raw(-1), None) {
Ok(_x) => {}, Ok(x) => {
Err(_err) => {}, // dbg!(x);
match x {
WaitStatus::Exited(pid, v) => {
println!("wait_all: pid {}: exited with status {}", pid, v);
},
WaitStatus::Signaled(pid, sig, _dumped) => {
println!("wait_all: pid {} killed with signal {}", pid, sig);
},
_ => {}
}
},
Err(err) => {
dbg!(err);
match err {
Errno::ECHILD => {
break 'wait;
},
_ => {}
}
},
}
// dbg!("sanity");
} }
} }