From 08405ba25168ca386da38b51108cd5af4bb39334 Mon Sep 17 00:00:00 2001 From: Solomon Jacobs Date: Sat, 14 Oct 2023 00:53:09 +0200 Subject: [PATCH 1/2] Create a supervisor --- Cargo.lock | 113 ++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/bin/supervisor.rs | 30 +++++++++++ 3 files changed, 144 insertions(+) create mode 100644 src/bin/supervisor.rs diff --git a/Cargo.lock b/Cargo.lock index 9288315..3f2a8db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,54 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -65,6 +113,52 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "futures" version = "0.3.28" @@ -160,6 +254,12 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.3.3" @@ -299,6 +399,7 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" name = "scheduler" version = "0.1.0" dependencies = [ + "clap", "futures", "libc", "tokio", @@ -344,6 +445,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "syn" version = "2.0.38" @@ -391,6 +498,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 5ceed2a..6f7fe44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clap = { version = "4.4.6", features = ["derive"] } futures = "0.3.28" libc = "0.2.149" tokio = { version = "1.33.0", features = ["full"] } diff --git a/src/bin/supervisor.rs b/src/bin/supervisor.rs new file mode 100644 index 0000000..7b246d8 --- /dev/null +++ b/src/bin/supervisor.rs @@ -0,0 +1,30 @@ +use clap::Parser; +use std::io::{self, Write}; +use std::process::Command; +use std::thread::sleep; +use std::time::Duration; + +#[derive(Parser)] +struct Arguments { + #[arg(short, long)] + command: String, + #[arg(short, long, default_value = "60")] + interval: u64, + #[clap(last = true)] + arguments: Vec, +} + +fn main() { + let arguments = Arguments::parse(); + + let mut command = Command::new(arguments.command); + command.args(arguments.arguments); + + loop { + let output = command.output().expect("Failed to execute command"); + io::stdout().write_all(&output.stdout).unwrap(); + io::stderr().write_all(&output.stderr).unwrap(); + println!("{:?}", output.status.code()); + sleep(Duration::from_secs(arguments.interval)); + } +} From 7df776ce32cdc2c1c232362997063463f037ed2d Mon Sep 17 00:00:00 2001 From: Solomon Jacobs Date: Sat, 14 Oct 2023 16:24:51 +0200 Subject: [PATCH 2/2] supervisor: move the async scheduler --- Cargo.lock | 81 +++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/bin/supervisor.rs | 54 ++++++++++++++++++++++++----- 3 files changed, 127 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f2a8db..db1dfd9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "anstream" version = "0.6.4" @@ -248,12 +259,32 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + [[package]] name = "heck" version = "0.4.1" @@ -327,6 +358,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + [[package]] name = "parking_lot" version = "0.12.1" @@ -403,6 +440,7 @@ dependencies = [ "futures", "libc", "tokio", + "tokio-util", ] [[package]] @@ -492,6 +530,43 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-util" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "futures-util", + "hashbrown", + "pin-project-lite", + "slab", + "tokio", + "tracing", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -504,6 +579,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 6f7fe44..2174963 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,4 @@ clap = { version = "4.4.6", features = ["derive"] } futures = "0.3.28" libc = "0.2.149" tokio = { version = "1.33.0", features = ["full"] } +tokio-util = { version = "0.7.9", features = ["full"] } diff --git a/src/bin/supervisor.rs b/src/bin/supervisor.rs index 7b246d8..381dccd 100644 --- a/src/bin/supervisor.rs +++ b/src/bin/supervisor.rs @@ -1,8 +1,9 @@ use clap::Parser; use std::io::{self, Write}; -use std::process::Command; -use std::thread::sleep; -use std::time::Duration; +use tokio::process::Command; +use tokio::signal::ctrl_c; +use tokio::time; +use tokio_util::sync::CancellationToken; #[derive(Parser)] struct Arguments { @@ -14,17 +15,52 @@ struct Arguments { arguments: Vec, } -fn main() { +#[tokio::main] +async fn main() { + let pid = std::process::id(); + println!("{pid}"); let arguments = Arguments::parse(); let mut command = Command::new(arguments.command); command.args(arguments.arguments); + let interval = time::interval(time::Duration::from_secs(arguments.interval)); + + let token = CancellationToken::new(); + let k = tokio::spawn(run(command, interval, token.clone())); + let _ = ctrl_c().await; + token.cancel(); + let _ = k.await; +} + +fn kill_gracefully(child_id: i32) { + unsafe { + libc::kill(child_id, libc::SIGTERM); + } +} + +async fn run(mut command: Command, mut interval: time::Interval, token: CancellationToken) { loop { - let output = command.output().expect("Failed to execute command"); - io::stdout().write_all(&output.stdout).unwrap(); - io::stderr().write_all(&output.stderr).unwrap(); - println!("{:?}", output.status.code()); - sleep(Duration::from_secs(arguments.interval)); + tokio::select! { + _ = interval.tick() => {} + _ = token.cancelled() => { return } + } + println!("Starting"); + let child = command.spawn().expect("Failed to execute command"); + if let Some(child_id) = child.id() { + tokio::select! { + output = child.wait_with_output() => { + let outcome = output.expect("Failed to execute command"); + io::stdout().write_all(&outcome.stdout).unwrap(); + io::stderr().write_all(&outcome.stderr).unwrap(); + println!("{:?}", outcome.status.code()); + } + _ = token.cancelled() => { + println!("KILLING"); + kill_gracefully(child_id as i32); + return + } + } + } } }