Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add stdio redirection example #119

Merged
merged 3 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
- ping
- dev_random
- ping_queue
- redirect_stdio
env:
DURATION: 10s
RUST_LOG: trace
Expand Down
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
/target
.direnv/
.vscode/
result
result

# For the redirect_stdio example
stdin
stdout
stderr
19 changes: 13 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
4 changes: 0 additions & 4 deletions examples/hello_part/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ license = "MIT OR Apache-2.0"
a653rs = { workspace = true, features = ["macros"] }
a653rs-postcard = { version = "0.4", features = ["alloc"] }
a653rs-linux.workspace = true
nix.workspace = true
memmap2.workspace = true
procfs.workspace = true
once_cell.workspace = true
serde = "1.0"
log = "0"
humantime = "2.1"
13 changes: 13 additions & 0 deletions examples/redirect_stdio/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions examples/redirect_stdio/redirect_stdio.yaml
Original file line number Diff line number Diff line change
@@ -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 ]
74 changes: 74 additions & 0 deletions examples/redirect_stdio/src/main.rs
Original file line number Diff line number Diff line change
@@ -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<T: AsRawFd, U: AsRef<Path>>(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())?;
sevenautumns marked this conversation as resolved.
Show resolved Hide resolved
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();
}
}
16 changes: 13 additions & 3 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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" ];
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -181,7 +189,7 @@
inherit (nixpkgs.lib) flatten;
in
flatten (map
({ name, partitions }: [
({ name, partitions, preRun ? "" }: [
{
name = "run-example-${name}";
command = ''
Expand All @@ -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";
Expand Down
3 changes: 2 additions & 1 deletion hypervisor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
6 changes: 6 additions & 0 deletions hypervisor/src/hypervisor/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ impl<'a> PartitionTimeframeScheduler<'a> {
return Ok(());
}

if let OperatingMode::Idle = self.partition.get_base_run().1.mode() {
trace!("Partition is IDLE, waiting till the end of the partition time window");
std::thread::sleep(self.timeout.remaining_time());
return Ok(());
}

// If we are in the normal mode at the beginning of the time frame,
// only then we may schedule the periodic process inside a partition
if let OperatingMode::Normal = self.partition.get_base_run().1.mode() {
Expand Down
2 changes: 1 addition & 1 deletion partition/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Loading