Skip to content

Commit 4964c48

Browse files
committed
Use pipe in shim , not use fifo directly
Do io copy like goshim Signed-off-by: jokemanfire <hu.dingyang@zte.com.cn>
1 parent 9d9cc05 commit 4964c48

File tree

3 files changed

+47
-18
lines changed

3 files changed

+47
-18
lines changed

crates/runc-shim/src/common.rs

+16-12
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ use std::{
3030

3131
use containerd_shim::{
3232
api::{ExecProcessRequest, Options},
33-
io_error, other, other_error,
34-
util::IntoOption,
35-
Error,
33+
io_error, other, other_error, Error,
3634
};
3735
use log::{debug, warn};
3836
use nix::{
@@ -44,7 +42,7 @@ use nix::{
4442
};
4543
use oci_spec::runtime::{LinuxNamespaceType, Spec};
4644
use runc::{
47-
io::{Io, NullIo, FIFO},
45+
io::{IOOption, Io, NullIo, PipedIo},
4846
options::GlobalOpts,
4947
Runc, Spawner,
5048
};
@@ -77,8 +75,8 @@ pub struct ProcessIO {
7775

7876
pub fn create_io(
7977
id: &str,
80-
_io_uid: u32,
81-
_io_gid: u32,
78+
io_uid: u32,
79+
io_gid: u32,
8280
stdio: &Stdio,
8381
) -> containerd_shim::Result<ProcessIO> {
8482
let mut pio = ProcessIO::default();
@@ -101,19 +99,25 @@ pub fn create_io(
10199

102100
if scheme == FIFO_SCHEME {
103101
debug!(
104-
"create named pipe io for container {}, stdin: {}, stdout: {}, stderr: {}",
102+
"create pipe io for container {}, stdin: {}, stdout: {}, stderr: {}",
105103
id,
106104
stdio.stdin.as_str(),
107105
stdio.stdout.as_str(),
108106
stdio.stderr.as_str()
109107
);
110-
let io = FIFO {
111-
stdin: stdio.stdin.to_string().none_if(|x| x.is_empty()),
112-
stdout: stdio.stdout.to_string().none_if(|x| x.is_empty()),
113-
stderr: stdio.stderr.to_string().none_if(|x| x.is_empty()),
108+
109+
if stdio.stdin.is_empty() {
110+
debug!("stdin is empty");
111+
}
112+
let opts = IOOption {
113+
open_stdin: !stdio.stdin.is_empty(),
114+
open_stdout: !stdio.stdout.is_empty(),
115+
open_stderr: !stdio.stderr.is_empty(),
114116
};
117+
let io = PipedIo::new(io_uid, io_gid, &opts).unwrap();
118+
pio.copy = true;
119+
115120
pio.io = Some(Arc::new(io));
116-
pio.copy = false;
117121
}
118122
Ok(pio)
119123
}

crates/runc-shim/src/processes.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use tokio::{
3737
sync::oneshot::{channel, Receiver, Sender},
3838
};
3939

40-
use crate::io::Stdio;
40+
use crate::{common::ProcessIO, io::Stdio};
4141

4242
#[allow(dead_code)]
4343
#[async_trait]
@@ -77,6 +77,7 @@ pub struct ProcessTemplate<S> {
7777
pub state: Status,
7878
pub id: String,
7979
pub stdio: Stdio,
80+
pub io: Option<Arc<ProcessIO>>,
8081
pub pid: i32,
8182
pub exit_code: i32,
8283
pub exited_at: Option<OffsetDateTime>,
@@ -92,6 +93,7 @@ impl<S> ProcessTemplate<S> {
9293
state: Status::CREATED,
9394
id: id.to_string(),
9495
stdio,
96+
io: None,
9597
pid: 0,
9698
exit_code: 0,
9799
exited_at: None,

crates/runc-shim/src/runc.rs

+28-5
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,10 @@ impl RuncFactory {
163163
(Some(s), None)
164164
} else {
165165
let pio = create_io(&id, opts.io_uid, opts.io_gid, stdio)?;
166-
create_opts.io = pio.io.as_ref().cloned();
167-
(None, Some(pio))
166+
let ref_pio = Arc::new(pio);
167+
create_opts.io = ref_pio.io.clone();
168+
init.io = Some(ref_pio.clone());
169+
(None, Some(ref_pio))
168170
};
169171

170172
let resp = init
@@ -178,6 +180,22 @@ impl RuncFactory {
178180
}
179181
return Err(runtime_error(bundle, e, "OCI runtime create failed").await);
180182
}
183+
if !init.stdio.stdin.is_empty() {
184+
let stdin_clone = init.stdio.stdin.clone();
185+
let stdin_w = init.stdin.clone();
186+
// Open the write side in advance to make sure read side will not block,
187+
// open it in another thread otherwise it will block too.
188+
tokio::spawn(async move {
189+
if let Ok(stdin_w_file) = OpenOptions::new()
190+
.write(true)
191+
.open(stdin_clone.as_str())
192+
.await
193+
{
194+
let mut lock_guard = stdin_w.lock().unwrap();
195+
*lock_guard = Some(stdin_w_file);
196+
}
197+
});
198+
}
181199
copy_io_or_console(init, socket, pio, init.lifecycle.exit_signal.clone()).await?;
182200
let pid = read_file_to_str(pid_path).await?.parse::<i32>()?;
183201
init.pid = pid;
@@ -232,6 +250,7 @@ impl ProcessFactory<ExecProcess> for RuncExecFactory {
232250
stderr: req.stderr.to_string(),
233251
terminal: req.terminal,
234252
},
253+
io: None,
235254
pid: 0,
236255
exit_code: 0,
237256
exited_at: None,
@@ -299,6 +318,7 @@ impl ProcessLifecycle<InitProcess> for RuncInitLifecycle {
299318
);
300319
}
301320
}
321+
302322
self.exit_signal.signal();
303323
Ok(())
304324
}
@@ -434,8 +454,10 @@ impl ProcessLifecycle<ExecProcess> for RuncExecLifecycle {
434454
(Some(s), None)
435455
} else {
436456
let pio = create_io(&p.id, self.io_uid, self.io_gid, &p.stdio)?;
437-
exec_opts.io = pio.io.as_ref().cloned();
438-
(None, Some(pio))
457+
let ref_pio = Arc::new(pio);
458+
exec_opts.io = ref_pio.io.clone();
459+
p.io = Some(ref_pio.clone());
460+
(None, Some(ref_pio))
439461
};
440462
//TODO checkpoint support
441463
let exec_result = self
@@ -698,7 +720,7 @@ where
698720
async fn copy_io_or_console<P>(
699721
p: &mut ProcessTemplate<P>,
700722
socket: Option<ConsoleSocket>,
701-
pio: Option<ProcessIO>,
723+
pio: Option<Arc<ProcessIO>>,
702724
exit_signal: Arc<ExitSignal>,
703725
) -> Result<()> {
704726
if p.stdio.terminal {
@@ -736,6 +758,7 @@ impl Spawner for ShimExecutor {
736758
}
737759
};
738760
let pid = child.id().unwrap();
761+
739762
let (stdout, stderr, exit_code) = tokio::join!(
740763
read_std(child.stdout),
741764
read_std(child.stderr),

0 commit comments

Comments
 (0)