runc: Set piped stdio as default

Signed-off-by: Zhang Tianyang <burning9699@gmail.com>
This commit is contained in:
Zhang Tianyang 2022-02-28 20:59:18 +08:00
parent f7335a88a9
commit dd90a9180f
1 changed files with 40 additions and 34 deletions

View File

@ -118,10 +118,10 @@ impl Runc {
let args = [&self.args, args].concat(); let args = [&self.args, args].concat();
let mut cmd = Command::new(&self.command); let mut cmd = Command::new(&self.command);
// Default to inherited stdio, and they may be override by command options. // Default to piped stdio, and they may be override by command options.
cmd.stdin(Stdio::null()) cmd.stdin(Stdio::null())
.stdout(Stdio::inherit()) .stdout(Stdio::piped())
.stderr(Stdio::inherit()); .stderr(Stdio::piped());
// NOTIFY_SOCKET introduces a special behavior in runc but should only be set if invoked from systemd // NOTIFY_SOCKET introduces a special behavior in runc but should only be set if invoked from systemd
cmd.args(&args).env_remove("NOTIFY_SOCKET"); cmd.args(&args).env_remove("NOTIFY_SOCKET");
@ -141,19 +141,16 @@ impl Runc {
let stderr = String::from_utf8_lossy(&result.stderr).to_string(); let stderr = String::from_utf8_lossy(&result.stderr).to_string();
if status.success() { if status.success() {
if combined_output { let output = if combined_output {
Ok(Response { stdout + stderr.as_str()
pid,
status,
output: stdout + stderr.as_str(),
})
} else { } else {
Ok(Response { stdout
pid, };
status, Ok(Response {
output: stdout, pid,
}) status,
} output,
})
} else { } else {
Err(Error::CommandFailed { Err(Error::CommandFailed {
status, status,
@ -209,10 +206,16 @@ impl Runc {
} }
args.push(id.to_string()); args.push(id.to_string());
let mut cmd = self.command(&args)?; let mut cmd = self.command(&args)?;
if let Some(ExecOpts { io: Some(io), .. }) = opts { match opts {
io.set(&mut cmd).map_err(|e| Error::IoSet(e.to_string()))?; Some(ExecOpts { io: Some(io), .. }) => {
io.set(&mut cmd).map_err(|e| Error::IoSet(e.to_string()))?;
self.launch(cmd, true)?;
io.close_after_start();
}
_ => {
self.launch(cmd, true)?;
}
} }
let _ = self.launch(cmd, true)?;
Ok(()) Ok(())
} }
@ -361,19 +364,16 @@ impl Runc {
} = execute(&Self::MONITOR, cmd).await?; } = execute(&Self::MONITOR, cmd).await?;
if status.success() { if status.success() {
if combined_output { let output = if combined_output {
Ok(Response { stdout + stderr.as_str()
pid: exit.pid,
status,
output: stdout + stderr.as_str(),
})
} else { } else {
Ok(Response { stdout
pid: exit.pid, };
status, Ok(Response {
output: stdout, pid: exit.pid,
}) status,
} output,
})
} else { } else {
Err(Error::CommandFailed { Err(Error::CommandFailed {
status, status,
@ -567,7 +567,7 @@ impl Runc {
#[cfg(test)] #[cfg(test)]
#[cfg(all(target_os = "linux", not(feature = "async")))] #[cfg(all(target_os = "linux", not(feature = "async")))]
mod tests { mod tests {
use super::io::PipedStdIo; use super::io::{InheritedStdIo, PipedStdIo};
use super::*; use super::*;
use std::sync::Arc; use std::sync::Arc;
@ -721,7 +721,9 @@ mod tests {
#[test] #[test]
fn test_output() { fn test_output() {
let opts = CreateOpts::new(); // test create cmd with inherit Io, expect empty cmd output
let mut opts = CreateOpts::new();
opts.io = Some(Arc::new(InheritedStdIo::new().unwrap()));
let echo_runc = echo_client(); let echo_runc = echo_client();
let response = echo_runc let response = echo_runc
.create("fake-id", "fake-bundle", Some(&opts)) .create("fake-id", "fake-bundle", Some(&opts))
@ -730,6 +732,7 @@ mod tests {
assert!(response.status.success()); assert!(response.status.success());
assert!(response.output.is_empty()); assert!(response.output.is_empty());
// test create cmd with pipe Io, expect nonempty cmd output
let mut opts = CreateOpts::new(); let mut opts = CreateOpts::new();
opts.io = Some(Arc::new(PipedStdIo::new().unwrap())); opts.io = Some(Arc::new(PipedStdIo::new().unwrap()));
let echo_runc = echo_client(); let echo_runc = echo_client();
@ -746,7 +749,7 @@ mod tests {
#[cfg(test)] #[cfg(test)]
#[cfg(all(target_os = "linux", feature = "async"))] #[cfg(all(target_os = "linux", feature = "async"))]
mod tests { mod tests {
use super::io::PipedStdIo; use super::io::{InheritedStdIo, PipedStdIo};
use super::*; use super::*;
use std::sync::Arc; use std::sync::Arc;
@ -918,7 +921,9 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_async_output() { async fn test_async_output() {
let opts = CreateOpts::new(); // test create cmd with inherit Io, expect empty cmd output
let mut opts = CreateOpts::new();
opts.io = Some(Arc::new(InheritedStdIo::new().unwrap()));
let echo_runc = echo_client(); let echo_runc = echo_client();
let response = echo_runc let response = echo_runc
.create("fake-id", "fake-bundle", Some(&opts)) .create("fake-id", "fake-bundle", Some(&opts))
@ -928,6 +933,7 @@ mod tests {
assert!(response.status.success()); assert!(response.status.success());
assert!(response.output.is_empty()); assert!(response.output.is_empty());
// test create cmd with pipe Io, expect nonempty cmd output
let mut opts = CreateOpts::new(); let mut opts = CreateOpts::new();
opts.io = Some(Arc::new(PipedStdIo::new().unwrap())); opts.io = Some(Arc::new(PipedStdIo::new().unwrap()));
let response = echo_runc let response = echo_runc