diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d33ff2a..33eae82 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -18,6 +18,7 @@ jobs: - ping - dev_random - ping_queue + - redirect_stdio env: DURATION: 10s RUST_LOG: trace diff --git a/.gitignore b/.gitignore index 356f9b8..50e1c50 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,9 @@ /target .direnv/ .vscode/ -result \ No newline at end of file +result + +# For the redirect_stdio example +stdin +stdout +stderr diff --git a/Cargo.lock b/Cargo.lock index ee58997..772b632 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,7 +33,7 @@ dependencies = [ [[package]] name = "a653rs-linux-core" -version = "0.1.0" +version = "0.2.0" dependencies = [ "a653rs", "anyhow", @@ -57,7 +57,7 @@ dependencies = [ [[package]] name = "a653rs-linux-hypervisor" -version = "0.1.0" +version = "0.2.0" dependencies = [ "a653rs", "a653rs-linux-core", @@ -555,10 +555,6 @@ dependencies = [ "a653rs-postcard", "humantime", "log", - "memmap2", - "nix", - "once_cell", - "procfs", "serde", ] @@ -1064,6 +1060,17 @@ dependencies = [ "getrandom", ] +[[package]] +name = "redirect_stdio" +version = "0.1.0" +dependencies = [ + "a653rs", + "a653rs-linux", + "anyhow", + "log", + "nix", +] + [[package]] name = "regex" version = "1.10.5" diff --git a/Cargo.toml b/Cargo.toml index 8ab41e7..f76b177 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,10 +15,12 @@ members = [ "examples/ping/client", "examples/ping/server", - "examples/dev_random", - "examples/ping_queue/client", "examples/ping_queue/server", + + "examples/dev_random", + + "examples/redirect_stdio" ] [workspace.package] @@ -38,6 +40,7 @@ repository = "https://github.com/DLR-FT/a653rs-linux/" a653rs = "0.6" a653rs-linux = { version = "0.2", path = "partition" } a653rs-linux-core = { version = "0.2", path = "core" } +anyhow = "1.0" log = "0" nix = { version = "0.29", features = ["socket", "process", "fs", "uio", "signal", "user", "mount", "event", "sched"] } memmap2 = "0.9" diff --git a/core/Cargo.toml b/core/Cargo.toml index 3885180..45e78b9 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -19,8 +19,8 @@ memmap2.workspace = true procfs.workspace = true polling.workspace = true itertools.workspace = true +anyhow.workspace = true -anyhow = "1.0" log = "0" walkdir = "2.3" serde = { version = "1.0", features = ["derive"] } diff --git a/examples/redirect_stdio/Cargo.toml b/examples/redirect_stdio/Cargo.toml new file mode 100644 index 0000000..76cf060 --- /dev/null +++ b/examples/redirect_stdio/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "redirect_stdio" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +a653rs = { workspace = true, features = ["macros"] } +a653rs-linux.workspace = true +log.workspace = true +nix.workspace = true +anyhow.workspace = true diff --git a/examples/redirect_stdio/redirect_stdio.yaml b/examples/redirect_stdio/redirect_stdio.yaml new file mode 100644 index 0000000..a52366a --- /dev/null +++ b/examples/redirect_stdio/redirect_stdio.yaml @@ -0,0 +1,12 @@ +major_frame: 1s +partitions: + - id: 0 + name: partition_0 + duration: 1s + offset: 0ms + period: 1s + image: ./target/x86_64-unknown-linux-musl/release/redirect_stdio + mounts: + - [ ./stdin, /stdin ] + - [ ./stdout, /stdout ] + - [ ./stderr, /stderr ] diff --git a/examples/redirect_stdio/src/main.rs b/examples/redirect_stdio/src/main.rs new file mode 100644 index 0000000..c13d3c9 --- /dev/null +++ b/examples/redirect_stdio/src/main.rs @@ -0,0 +1,74 @@ +use std::fs::OpenOptions; +use std::os::fd::AsRawFd; +use std::path::Path; + +use a653rs::partition; +use a653rs::prelude::PartitionExt; +use a653rs_linux::partition::ApexLogger; +use anyhow::Result; +use log::LevelFilter; + +fn replace_stdio>(stdio: T, new: U, write: bool) -> Result<()> { + let new = OpenOptions::new() + .write(write) + .read(!write) + .truncate(write) + .open(new)?; + nix::unistd::dup2(new.as_raw_fd(), stdio.as_raw_fd())?; + Ok(()) +} + +fn main() { + replace_stdio(std::io::stdin(), "/stdin", false).unwrap(); + replace_stdio(std::io::stdout(), "/stdout", true).unwrap(); + replace_stdio(std::io::stderr(), "/stderr", true).unwrap(); + + ApexLogger::install_panic_hook(); + ApexLogger::install_logger(LevelFilter::Trace).unwrap(); + + redirect_stdio::Partition.run() +} + +#[partition(a653rs_linux::partition::ApexLinuxPartition)] +mod redirect_stdio { + use log::info; + use std::io::BufRead; + + #[start(cold)] + fn cold_start(mut ctx: start::Context) { + // create and start an aperiodic process + ctx.create_process_0().unwrap().start().unwrap(); + } + + // do the same as a cold_start + #[start(warm)] + fn warm_start(ctx: start::Context) { + cold_start(ctx); + } + + // this aperiodic process opens /dev/random and reads some random bytes from it + #[aperiodic( + time_capacity = "Infinite", + stack_size = "8KB", + base_priority = 1, + deadline = "Soft" + )] + fn process_0(ctx: process_0::Context) { + info!("started process with redirected stdio/stdout/stderr"); + + info!("Reading stdin to stdout"); + println!("Start reading stdin to stdout"); + let stdin = std::io::stdin(); + for line in stdin.lock().lines() { + println!("{}", line.unwrap()) + } + println!("Finished reading stdin to stdout"); + + info!("Writing messages to stderr"); + eprintln!("Error was encountered: None"); + eprintln!("But it was printed to stderr"); + + info!("Terminating partition"); + ctx.set_partition_mode(OperatingMode::Idle).unwrap(); + } +} diff --git a/flake.nix b/flake.nix index ee61b24..296f20f 100644 --- a/flake.nix +++ b/flake.nix @@ -71,6 +71,14 @@ name = "hello_part_no_macros"; partitions = [ "hello_part_no_macros" ]; } + { + name = "redirect_stdio"; + partitions = [ "redirect_stdio" ]; + preRun = '' + touch $PRJ_ROOT/std{out,err} + echo $'hello\nworld!\n' > $PRJ_ROOT/stdin + ''; + } { name = "fuel_tank"; partitions = [ "fuel_tank_simulation" "fuel_tank_controller" ]; @@ -103,7 +111,7 @@ cargoTestOptions = x: x ++ [ "--package" pname ]; } // env; } // (builtins.listToAttrs (builtins.map - ({ name, partitions }: { + ({ name, partitions, ... }: { name = "example-${name}"; value = naersk-lib.buildPackage rec { @@ -181,7 +189,7 @@ inherit (nixpkgs.lib) flatten; in flatten (map - ({ name, partitions }: [ + ({ name, partitions, preRun ? "" }: [ { name = "run-example-${name}"; command = '' @@ -192,8 +200,10 @@ # prepend PATH so that partition images can be found PATH="target/${rust-target}/release:$PATH" + ${preRun} + # (build &) run hypervisor - RUST_LOG=''${RUST_LOG:=trace} cargo run --package a653rs-linux-hypervisor --release -- examples/${name}/${name}.yaml $@ + RUST_LOG=''${RUST_LOG:=trace} cargo run --package a653rs-linux-hypervisor --release -- "examples/${name}/${name}.yaml" $@ ''; help = "Run the ${name} example, consisting of the partitions: ${concatStringsSep "," partitions}"; category = "example"; diff --git a/hypervisor/Cargo.toml b/hypervisor/Cargo.toml index 38ea075..71cc063 100644 --- a/hypervisor/Cargo.toml +++ b/hypervisor/Cargo.toml @@ -21,7 +21,8 @@ polling.workspace = true itertools.workspace = true once_cell.workspace = true bytesize.workspace = true -anyhow = "1.0" +anyhow.workspace = true + tempfile = "3.3" clone3 = "0.2" serde = { version = "1.0", features = ["derive"] } diff --git a/partition/Cargo.toml b/partition/Cargo.toml index ccd46c3..4122f25 100644 --- a/partition/Cargo.toml +++ b/partition/Cargo.toml @@ -24,9 +24,9 @@ memmap2.workspace = true procfs.workspace = true polling.workspace = true once_cell.workspace = true +anyhow.workspace = true lazy_static = "1.4" -anyhow = "1.0" log.workspace = true tinyvec = "1.6" oneshot = "0.1.6"