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

Support being used as a binfmt_misc handler. #54

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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 Cargo.lock

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

4 changes: 3 additions & 1 deletion crates/krun-guest/src/bin/krun-guest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ fn main() -> Result<()> {
configure_network()?;

if let Some(hidpipe_client_path) = find_in_path("hidpipe-client")? {
Command::new(hidpipe_client_path).arg(format!("{}", options.uid)).spawn()?;
Command::new(hidpipe_client_path)
.arg(format!("{}", options.uid))
.spawn()?;
}

let run_path = match setup_user(options.username, options.uid, options.gid) {
Expand Down
2 changes: 1 addition & 1 deletion crates/krun-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ env_logger = { workspace = true, features = ["auto-color", "humantime", "unstabl
log = { workspace = true, features = ["kv"] }
serde = { workspace = true, features = [] }
serde_json = { workspace = true, features = ["std"] }
tokio = { workspace = true, features = ["io-util", "macros", "net", "process", "rt-multi-thread", "sync"] }
tokio = { workspace = true, features = ["io-util", "macros", "net", "process", "rt-multi-thread", "sync", "time"] }
tokio-stream = { workspace = true, features = ["net", "sync"] }
utils = { workspace = true, features = [] }

Expand Down
75 changes: 23 additions & 52 deletions crates/krun-server/src/bin/krun-server.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::os::unix::process::ExitStatusExt as _;

use anyhow::Result;
use krun_server::cli_options::options;
use krun_server::server::{Server, State};
use log::error;
use std::time::Duration;
use tokio::net::TcpListener;
use tokio::process::Command;
use tokio::sync::watch;
use tokio::time;
use tokio::time::Instant;
use tokio_stream::wrappers::WatchStream;
use tokio_stream::StreamExt as _;

Expand All @@ -23,18 +23,14 @@ async fn main() -> Result<()> {
let mut server = Server::new(listener, state_tx);
server.run().await;
});
let command_status = Command::new(&options.command)
.args(options.command_args)
.status();
tokio::pin!(command_status);
let mut state_rx = WatchStream::new(state_rx);

let mut server_died = false;
let mut command_exited = false;
let mut state_rx = WatchStream::from_changes(state_rx);
let far_future = Duration::from_secs(3600 * 24 * 365);
let linger_timer = time::sleep(far_future);
tokio::pin!(linger_timer);

loop {
tokio::select! {
res = &mut server_handle, if !server_died => {
res = &mut server_handle => {
// If an error is received here, accepting connections from the
// TCP listener failed due to non-transient errors and the
// server is giving up and shutting down.
Expand All @@ -43,51 +39,26 @@ async fn main() -> Result<()> {
// not bubble up to this point.
if let Err(err) = res {
error!(err:% = err; "server task failed");
server_died = true;
}
},
res = &mut command_status, if !command_exited => {
match res {
Ok(status) => {
if !status.success() {
if let Some(code) = status.code() {
eprintln!(
"{:?} process exited with status code: {code}",
options.command
);
} else {
eprintln!(
"{:?} process terminated by signal: {}",
options.command,
status
.signal()
.expect("either one of status code or signal should be set")
);
}
}
},
Err(err) => {
eprintln!(
"Failed to execute {:?} as child process: {err}",
options.command
);
},
return Ok(());
}
command_exited = true;
},
Some(state) = state_rx.next(), if command_exited => {
Some(state) = state_rx.next() => {
if state.connection_idle() && state.child_processes() == 0 {
// Server is idle (not currently handling an accepted
// incoming connection) and no more child processes.
// We're done.
return Ok(());
linger_timer.as_mut().reset(Instant::now() + Duration::from_secs(10));
} else {
linger_timer.as_mut().reset(Instant::now() + far_future);
println!(
"Waiting for {} other commands launched through this krun server to exit...",
state.child_processes()
);
}
println!(
"Waiting for {} other commands launched through this krun server to exit...",
state.child_processes()
);
println!("Press Ctrl+C to force quit");
},
_tick = &mut linger_timer => {
// Server is idle (not currently handling an accepted
// incoming connection) and no more child processes.
// We're done.
return Ok(());
}
}
}
}
19 changes: 2 additions & 17 deletions crates/krun-server/src/cli_options.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
use std::path::PathBuf;

use bpaf::{any, construct, env, positional, OptionParser, Parser};
use bpaf::{construct, env, OptionParser, Parser};

#[derive(Clone, Debug)]
pub struct Options {
pub server_port: u32,
pub command: PathBuf,
pub command_args: Vec<String>,
}

pub fn options() -> OptionParser<Options> {
Expand All @@ -16,19 +12,8 @@ pub fn options() -> OptionParser<Options> {
.argument("SERVER_PORT")
.fallback(3334)
.display_fallback();
let command = positional("COMMAND");
let command_args = any::<String, _, _>("COMMAND_ARGS", |arg| {
(!["--help", "-h"].contains(&&*arg)).then_some(arg)
})
.many();

construct!(Options {
server_port,
// positionals
command,
command_args,
})
.to_options()
construct!(Options { server_port }).to_options()
}

#[cfg(test)]
Expand Down
4 changes: 3 additions & 1 deletion crates/krun-server/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,9 @@ async fn handle_connection(mut stream: BufStream<TcpStream>) -> Result<(PathBuf,
command,
command_args,
env,
cwd,
} = read_request(&mut stream).await?;
debug!(command:?, command_args:?, env:?; "received launch request");
debug!(command:?, command_args:?, env:?, cwd:?; "received launch request");
envs.extend(env);

let (stdout, stderr) = make_stdout_stderr(&command, &envs)?;
Expand All @@ -176,6 +177,7 @@ async fn handle_connection(mut stream: BufStream<TcpStream>) -> Result<(PathBuf,
.stdin(Stdio::null())
.stdout(stdout)
.stderr(stderr)
.current_dir(cwd)
.spawn()
.with_context(|| format!("Failed to execute {command:?} as child process"));
if let Err(err) = &res {
Expand Down
1 change: 1 addition & 0 deletions crates/krun/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ rustix = { workspace = true, features = ["process", "std", "use-libc-auxv"] }
serde = { workspace = true, features = [] }
serde_json = { workspace = true, features = ["std"] }
utils = { workspace = true, features = [] }
uuid = { workspace = true, features = ["v4"] }

[features]
default = []
Loading