Merge pull request #61 from abel-von/add-update-stats
[async] pass all integration tests
This commit is contained in:
commit
d27767af57
|
|
@ -63,11 +63,6 @@ jobs:
|
|||
- name: Checkout extensions
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install shim
|
||||
run: |
|
||||
cargo build --release --bin containerd-shim-runc-v2-rs
|
||||
sudo install -D ./target/release/containerd-shim-runc-v2-rs /usr/local/bin/
|
||||
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.17.5'
|
||||
|
|
@ -101,9 +96,26 @@ jobs:
|
|||
sudo -E PATH=$PATH install bin/containerd /usr/local/bin/
|
||||
working-directory: src/github.com/containerd/containerd
|
||||
|
||||
- name: Install shim
|
||||
run: |
|
||||
cargo build --release --bin containerd-shim-runc-v2-rs
|
||||
sudo install -D ./target/release/containerd-shim-runc-v2-rs /usr/local/bin/
|
||||
|
||||
- name: Integration
|
||||
env:
|
||||
GOPROXY: direct
|
||||
TEST_RUNTIME: "io.containerd.runc.v2-rs"
|
||||
run: sudo -E PATH=$PATH TESTFLAGS_PARALLEL=1 make integration TESTFLAGS_RACE=-race EXTRA_TESTFLAGS=-no-criu
|
||||
working-directory: src/github.com/containerd/containerd
|
||||
|
||||
- name: Install async shim
|
||||
run: |
|
||||
cargo build --release --all-features --bin containerd-shim-runc-v2-rs
|
||||
sudo install -D ./target/release/containerd-shim-runc-v2-rs /usr/local/bin/
|
||||
|
||||
- name: Integration for async shim
|
||||
env:
|
||||
GOPROXY: direct
|
||||
TEST_RUNTIME: "io.containerd.runc.v2-rs"
|
||||
run: sudo -E PATH=$PATH TESTFLAGS_PARALLEL=1 make integration TESTFLAGS_RACE=-race EXTRA_TESTFLAGS=-no-criu
|
||||
working-directory: src/github.com/containerd/containerd
|
||||
|
|
@ -36,7 +36,4 @@ tokio = { version = "1.17.0", features = ["full"], optional = true }
|
|||
futures = { version = "0.3.21", optional = true }
|
||||
|
||||
containerd-shim = { path = "../shim", version = "0.3.0" }
|
||||
runc = { path = "../runc", version = "0.2.0" }
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
cgroups-rs = "0.2.9"
|
||||
runc = { path = "../runc", version = "0.2.0" }
|
||||
|
|
@ -39,7 +39,7 @@ use containerd_shim::util::{read_options, read_runtime, read_spec, write_str_to_
|
|||
use containerd_shim::{io_error, Config, Context, DeleteResponse, Error, StartOpts};
|
||||
|
||||
use crate::asynchronous::runc::{RuncContainer, RuncFactory};
|
||||
use crate::common::create_runc;
|
||||
use crate::common::{create_runc, has_shared_pid_namespace};
|
||||
use crate::common::{ShimExecutor, GROUP_LABELS};
|
||||
|
||||
mod runc;
|
||||
|
|
@ -142,7 +142,7 @@ async fn process_exits(
|
|||
// pid belongs to container init process
|
||||
if cont.init.pid == pid {
|
||||
// kill all children process if the container has a private PID namespace
|
||||
if cont.init.lifecycle.should_kill_all_on_exit(&bundle).await {
|
||||
if should_kill_all_on_exit(&bundle).await {
|
||||
cont.kill(None, 9, true).await.unwrap_or_else(|e| {
|
||||
error!("failed to kill init's children: {}", e)
|
||||
});
|
||||
|
|
@ -203,3 +203,16 @@ async fn forward(
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn should_kill_all_on_exit(bundle_path: &str) -> bool {
|
||||
match read_spec(bundle_path).await {
|
||||
Ok(spec) => has_shared_pid_namespace(&spec),
|
||||
Err(e) => {
|
||||
error!(
|
||||
"failed to read spec when call should_kill_all_on_exit: {}",
|
||||
e
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use async_trait::async_trait;
|
|||
use log::{debug, error};
|
||||
use nix::sys::signal::kill;
|
||||
use nix::unistd::Pid;
|
||||
use oci_spec::runtime::{LinuxNamespaceType, Process};
|
||||
use oci_spec::runtime::{LinuxResources, Process};
|
||||
use tokio::fs::{File, OpenOptions};
|
||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite};
|
||||
|
||||
|
|
@ -40,13 +40,13 @@ use containerd_shim::asynchronous::monitor::{
|
|||
use containerd_shim::asynchronous::processes::{ProcessLifecycle, ProcessTemplate};
|
||||
use containerd_shim::io::Stdio;
|
||||
use containerd_shim::monitor::{ExitEvent, Subject, Topic};
|
||||
use containerd_shim::protos::api::ProcessInfo;
|
||||
use containerd_shim::protos::cgroups::metrics::Metrics;
|
||||
use containerd_shim::protos::protobuf::{CodedInputStream, Message};
|
||||
use containerd_shim::util::{
|
||||
asyncify, mkdir, mount_rootfs, read_file_to_str, read_spec, write_options, write_runtime,
|
||||
asyncify, mkdir, mount_rootfs, read_file_to_str, write_options, write_runtime,
|
||||
};
|
||||
use containerd_shim::Console;
|
||||
use containerd_shim::{io_error, other, Error};
|
||||
use containerd_shim::{other_error, Result};
|
||||
use containerd_shim::{io_error, other, other_error, Console, Error, ExitSignal, Result};
|
||||
use runc::{Command, Runc, Spawner};
|
||||
|
||||
use crate::common::receive_socket;
|
||||
|
|
@ -116,7 +116,7 @@ impl ContainerFactory<RuncContainer> for RuncFactory {
|
|||
let mut init = InitProcess::new(
|
||||
id,
|
||||
stdio,
|
||||
RuncInitLifecycle::new(runc.clone(), opts.clone(), rootfs, bundle),
|
||||
RuncInitLifecycle::new(runc.clone(), opts.clone(), bundle),
|
||||
);
|
||||
|
||||
let config = CreateConfig::default();
|
||||
|
|
@ -149,7 +149,7 @@ impl RuncFactory {
|
|||
let bundle = &init.lifecycle.bundle;
|
||||
let pid_path = Path::new(bundle).join(INIT_PID_FILE);
|
||||
let mut create_opts = runc::options::CreateOpts::new()
|
||||
.pid_file(pid_path.to_owned())
|
||||
.pid_file(&pid_path)
|
||||
.no_pivot(opts.no_pivot_root)
|
||||
.no_new_keyring(opts.no_new_keyring)
|
||||
.detach(false);
|
||||
|
|
@ -174,7 +174,7 @@ impl RuncFactory {
|
|||
}
|
||||
return Err(other!("failed to create runc container: {}", e));
|
||||
}
|
||||
copy_io_or_console(init, socket, pio).await?;
|
||||
copy_io_or_console(init, socket, pio, init.lifecycle.exit_signal.clone()).await?;
|
||||
let pid = read_file_to_str(pid_path).await?.parse::<i32>()?;
|
||||
init.pid = pid;
|
||||
Ok(())
|
||||
|
|
@ -206,25 +206,24 @@ impl ProcessFactory<ExecProcess> for RuncExecFactory {
|
|||
exited_at: None,
|
||||
wait_chan_tx: vec![],
|
||||
console: None,
|
||||
lifecycle: RuncExecLifecycle {
|
||||
lifecycle: Arc::from(RuncExecLifecycle {
|
||||
runtime: self.runtime.clone(),
|
||||
bundle: self.bundle.to_string(),
|
||||
container_id: req.id.to_string(),
|
||||
io_uid: self.io_uid,
|
||||
io_gid: self.io_gid,
|
||||
spec: p,
|
||||
},
|
||||
exit_signal: Default::default(),
|
||||
}),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RuncInitLifecycle {
|
||||
runtime: Runc,
|
||||
opts: Options,
|
||||
bundle: String,
|
||||
rootfs: PathBuf,
|
||||
work_dir: PathBuf,
|
||||
exit_signal: Arc<ExitSignal>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
|
@ -268,12 +267,61 @@ impl ProcessLifecycle<InitProcess> for RuncInitLifecycle {
|
|||
Ok(())
|
||||
}
|
||||
})
|
||||
.map_err(other_error!(e, "failed delete"))
|
||||
.map_err(other_error!(e, "failed delete"))?;
|
||||
self.exit_signal.signal();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn update(&self, p: &mut InitProcess, resources: &LinuxResources) -> Result<()> {
|
||||
if p.pid <= 0 {
|
||||
return Err(other!(
|
||||
"failed to update resources because init process is {}",
|
||||
p.pid
|
||||
));
|
||||
}
|
||||
containerd_shim::cgroup::update_resources(p.pid as u32, resources)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
async fn update(&self, _p: &mut InitProcess, _resources: &LinuxResources) -> Result<()> {
|
||||
Err(Error::Unimplemented("update resource".to_string()))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn stats(&self, p: &InitProcess) -> Result<Metrics> {
|
||||
if p.pid <= 0 {
|
||||
return Err(other!(
|
||||
"failed to collect metrics because init process is {}",
|
||||
p.pid
|
||||
));
|
||||
}
|
||||
containerd_shim::cgroup::collect_metrics(p.pid as u32)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
async fn stats(&self, _p: &InitProcess) -> Result<Metrics> {
|
||||
Err(Error::Unimplemented("process stats".to_string()))
|
||||
}
|
||||
|
||||
async fn ps(&self, p: &InitProcess) -> Result<Vec<ProcessInfo>> {
|
||||
let pids = self
|
||||
.runtime
|
||||
.ps(&*p.id)
|
||||
.await
|
||||
.map_err(other_error!(e, "failed to execute runc ps"))?;
|
||||
Ok(pids
|
||||
.iter()
|
||||
.map(|&x| ProcessInfo {
|
||||
pid: x as u32,
|
||||
..Default::default()
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl RuncInitLifecycle {
|
||||
pub fn new(runtime: Runc, opts: Options, rootfs: PathBuf, bundle: &str) -> Self {
|
||||
pub fn new(runtime: Runc, opts: Options, bundle: &str) -> Self {
|
||||
let work_dir = Path::new(bundle).join("work");
|
||||
let mut opts = opts;
|
||||
if opts.get_criu_path().is_empty() {
|
||||
|
|
@ -283,39 +331,11 @@ impl RuncInitLifecycle {
|
|||
runtime,
|
||||
opts,
|
||||
bundle: bundle.to_string(),
|
||||
rootfs,
|
||||
work_dir,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn should_kill_all_on_exit(&mut self, bundle_path: &str) -> bool {
|
||||
match read_spec(bundle_path).await {
|
||||
Ok(spec) => match spec.linux() {
|
||||
None => true,
|
||||
Some(linux) => match linux.namespaces() {
|
||||
None => true,
|
||||
Some(namespaces) => {
|
||||
for ns in namespaces {
|
||||
if ns.typ() == LinuxNamespaceType::Pid && ns.path().is_none() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
},
|
||||
},
|
||||
Err(e) => {
|
||||
error!(
|
||||
"failed to read spec when call should_kill_all_on_exit: {}",
|
||||
e
|
||||
);
|
||||
false
|
||||
}
|
||||
exit_signal: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RuncExecLifecycle {
|
||||
runtime: Runc,
|
||||
bundle: String,
|
||||
|
|
@ -323,6 +343,7 @@ pub struct RuncExecLifecycle {
|
|||
io_uid: u32,
|
||||
io_gid: u32,
|
||||
spec: Process,
|
||||
exit_signal: Arc<ExitSignal>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
|
@ -355,7 +376,7 @@ impl ProcessLifecycle<ExecProcess> for RuncExecLifecycle {
|
|||
}
|
||||
return Err(other!("failed to start runc exec: {}", e));
|
||||
}
|
||||
copy_io_or_console(p, socket, pio).await?;
|
||||
copy_io_or_console(p, socket, pio, p.lifecycle.exit_signal.clone()).await?;
|
||||
let pid = read_file_to_str(pid_path).await?.parse::<i32>()?;
|
||||
p.pid = pid;
|
||||
p.state = Status::RUNNING;
|
||||
|
|
@ -385,11 +406,28 @@ impl ProcessLifecycle<ExecProcess> for RuncExecLifecycle {
|
|||
}
|
||||
|
||||
async fn delete(&self, _p: &mut ExecProcess) -> containerd_shim::Result<()> {
|
||||
self.exit_signal.signal();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update(&self, _p: &mut ExecProcess, _resources: &LinuxResources) -> Result<()> {
|
||||
Err(Error::Unimplemented("exec update".to_string()))
|
||||
}
|
||||
|
||||
async fn stats(&self, _p: &ExecProcess) -> Result<Metrics> {
|
||||
Err(Error::Unimplemented("exec stats".to_string()))
|
||||
}
|
||||
|
||||
async fn ps(&self, _p: &ExecProcess) -> Result<Vec<ProcessInfo>> {
|
||||
Err(Error::Unimplemented("exec ps".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
async fn copy_console(console_socket: &ConsoleSocket, stdio: &Stdio) -> Result<Console> {
|
||||
async fn copy_console(
|
||||
console_socket: &ConsoleSocket,
|
||||
stdio: &Stdio,
|
||||
exit_signal: Arc<ExitSignal>,
|
||||
) -> Result<Console> {
|
||||
debug!("copy_console: waiting for runtime to send console fd");
|
||||
let stream = console_socket.accept().await?;
|
||||
let fd = asyncify(move || -> Result<RawFd> { receive_socket(stream.as_raw_fd()) }).await?;
|
||||
|
|
@ -400,13 +438,28 @@ async fn copy_console(console_socket: &ConsoleSocket, stdio: &Stdio) -> Result<C
|
|||
.try_clone()
|
||||
.await
|
||||
.map_err(io_error!(e, "failed to clone console file"))?;
|
||||
let stdin = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open(stdio.stdin.as_str())
|
||||
.await
|
||||
.map_err(io_error!(e, "open stdin"))?;
|
||||
spawn_copy(stdin, console_stdin, None::<fn()>);
|
||||
let stdin_fut = async {
|
||||
OpenOptions::new()
|
||||
.read(true)
|
||||
.open(stdio.stdin.as_str())
|
||||
.await
|
||||
};
|
||||
let stdin_w_fut = async {
|
||||
OpenOptions::new()
|
||||
.write(true)
|
||||
.open(stdio.stdin.as_str())
|
||||
.await
|
||||
};
|
||||
let (stdin, stdin_w) =
|
||||
tokio::try_join!(stdin_fut, stdin_w_fut).map_err(io_error!(e, "open stdin"))?;
|
||||
spawn_copy(
|
||||
stdin,
|
||||
console_stdin,
|
||||
exit_signal.clone(),
|
||||
Some(move || {
|
||||
drop(stdin_w);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if !stdio.stdout.is_empty() {
|
||||
|
|
@ -430,6 +483,7 @@ async fn copy_console(console_socket: &ConsoleSocket, stdio: &Stdio) -> Result<C
|
|||
spawn_copy(
|
||||
console_stdout,
|
||||
stdout,
|
||||
exit_signal,
|
||||
Some(move || {
|
||||
drop(stdout_r);
|
||||
}),
|
||||
|
|
@ -441,7 +495,7 @@ async fn copy_console(console_socket: &ConsoleSocket, stdio: &Stdio) -> Result<C
|
|||
Ok(console)
|
||||
}
|
||||
|
||||
pub async fn copy_io(pio: &ProcessIO, stdio: &Stdio) -> Result<()> {
|
||||
pub async fn copy_io(pio: &ProcessIO, stdio: &Stdio, exit_signal: Arc<ExitSignal>) -> Result<()> {
|
||||
if !pio.copy {
|
||||
return Ok(());
|
||||
};
|
||||
|
|
@ -454,8 +508,7 @@ pub async fn copy_io(pio: &ProcessIO, stdio: &Stdio) -> Result<()> {
|
|||
.open(stdio.stdin.as_str())
|
||||
.await
|
||||
.map_err(io_error!(e, "open stdin"))?;
|
||||
//let closer = io.stdin().unwrap();
|
||||
spawn_copy(stdin, w, None::<fn()>);
|
||||
spawn_copy(stdin, w, exit_signal.clone(), None::<fn()>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -477,6 +530,7 @@ pub async fn copy_io(pio: &ProcessIO, stdio: &Stdio) -> Result<()> {
|
|||
spawn_copy(
|
||||
r,
|
||||
stdout,
|
||||
exit_signal.clone(),
|
||||
Some(move || {
|
||||
drop(stdout_r);
|
||||
}),
|
||||
|
|
@ -502,6 +556,7 @@ pub async fn copy_io(pio: &ProcessIO, stdio: &Stdio) -> Result<()> {
|
|||
spawn_copy(
|
||||
r,
|
||||
stderr,
|
||||
exit_signal,
|
||||
Some(move || {
|
||||
drop(stderr_r);
|
||||
}),
|
||||
|
|
@ -513,7 +568,7 @@ pub async fn copy_io(pio: &ProcessIO, stdio: &Stdio) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn spawn_copy<R, W, F>(from: R, to: W, on_close: Option<F>)
|
||||
fn spawn_copy<R, W, F>(from: R, to: W, exit_signal: Arc<ExitSignal>, on_close: Option<F>)
|
||||
where
|
||||
R: AsyncRead + Send + Unpin + 'static,
|
||||
W: AsyncWrite + Send + Unpin + 'static,
|
||||
|
|
@ -522,12 +577,16 @@ where
|
|||
let mut src = from;
|
||||
let mut dst = to;
|
||||
tokio::spawn(async move {
|
||||
tokio::io::copy(&mut src, &mut dst)
|
||||
.await
|
||||
.unwrap_or_else(|e| {
|
||||
error!("copy io failed {}", e);
|
||||
0
|
||||
});
|
||||
tokio::select! {
|
||||
_ = exit_signal.wait() => {
|
||||
debug!("container exit, copy task should exit too");
|
||||
},
|
||||
res = tokio::io::copy(&mut src, &mut dst) => {
|
||||
if let Err(e) = res {
|
||||
error!("copy io failed {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(f) = on_close {
|
||||
f();
|
||||
}
|
||||
|
|
@ -538,22 +597,23 @@ async fn copy_io_or_console<P>(
|
|||
p: &mut ProcessTemplate<P>,
|
||||
socket: Option<ConsoleSocket>,
|
||||
pio: Option<ProcessIO>,
|
||||
exit_signal: Arc<ExitSignal>,
|
||||
) -> Result<()> {
|
||||
if p.stdio.terminal {
|
||||
if let Some(console_socket) = socket {
|
||||
let console_result = copy_console(&console_socket, &p.stdio).await;
|
||||
let console_result = copy_console(&console_socket, &p.stdio, exit_signal).await;
|
||||
console_socket.clean().await;
|
||||
match console_result {
|
||||
Ok(c) => {
|
||||
p.console = Some(c);
|
||||
}
|
||||
Err(e) => {
|
||||
console_socket.clean().await;
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(pio) = pio {
|
||||
copy_io(&pio, &p.stdio).await?;
|
||||
copy_io(&pio, &p.stdio, exit_signal).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ use nix::cmsg_space;
|
|||
use nix::sys::socket::{recvmsg, ControlMessageOwned, MsgFlags};
|
||||
use nix::sys::termios::tcgetattr;
|
||||
use nix::sys::uio::IoVec;
|
||||
use oci_spec::runtime::{LinuxNamespaceType, Spec};
|
||||
|
||||
use containerd_shim::api::{ExecProcessRequest, Options};
|
||||
use containerd_shim::io::Stdio;
|
||||
|
|
@ -200,3 +201,20 @@ pub fn receive_socket(stream_fd: RawFd) -> containerd_shim::Result<RawFd> {
|
|||
tcgetattr(fds[0])?;
|
||||
Ok(fds[0])
|
||||
}
|
||||
|
||||
pub fn has_shared_pid_namespace(spec: &Spec) -> bool {
|
||||
match spec.linux() {
|
||||
None => true,
|
||||
Some(linux) => match linux.namespaces() {
|
||||
None => true,
|
||||
Some(namespaces) => {
|
||||
for ns in namespaces {
|
||||
if ns.typ() == LinuxNamespaceType::Pid && ns.path().is_none() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ use std::sync::Arc;
|
|||
|
||||
use containerd_shim::ExitSignal;
|
||||
|
||||
mod cgroup;
|
||||
mod container;
|
||||
mod io;
|
||||
mod runc;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,9 @@ use shim::Console;
|
|||
use shim::{other, other_error};
|
||||
|
||||
use crate::common;
|
||||
use crate::common::{create_io, CreateConfig, ShimExecutor, INIT_PID_FILE};
|
||||
use crate::common::{
|
||||
create_io, has_shared_pid_namespace, CreateConfig, ShimExecutor, INIT_PID_FILE,
|
||||
};
|
||||
use crate::synchronous::container::{
|
||||
CommonContainer, CommonProcess, Container, ContainerFactory, Process,
|
||||
};
|
||||
|
|
@ -294,7 +296,7 @@ impl Container for RuncContainer {
|
|||
#[cfg(target_os = "linux")]
|
||||
fn stats(&self) -> Result<Metrics> {
|
||||
let pid = self.common.init.pid() as u32;
|
||||
crate::synchronous::cgroup::collect_metrics(pid)
|
||||
containerd_shim::cgroup::collect_metrics(pid)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
|
|
@ -305,7 +307,7 @@ impl Container for RuncContainer {
|
|||
#[cfg(target_os = "linux")]
|
||||
fn update(&mut self, resources: &LinuxResources) -> Result<()> {
|
||||
let pid = self.common.init.pid() as u32;
|
||||
crate::synchronous::cgroup::update_metrics(pid, resources)
|
||||
containerd_shim::cgroup::update_resources(pid, resources)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
|
|
@ -353,20 +355,7 @@ impl Container for RuncContainer {
|
|||
impl RuncContainer {
|
||||
pub(crate) fn should_kill_all_on_exit(&mut self, bundle_path: &str) -> bool {
|
||||
match read_spec_from_file(bundle_path) {
|
||||
Ok(spec) => match spec.linux() {
|
||||
None => true,
|
||||
Some(linux) => match linux.namespaces() {
|
||||
None => true,
|
||||
Some(namespaces) => {
|
||||
for ns in namespaces {
|
||||
if ns.typ() == LinuxNamespaceType::Pid && ns.path().is_none() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
},
|
||||
},
|
||||
Ok(spec) => has_shared_pid_namespace(&spec),
|
||||
Err(e) => {
|
||||
error!("should_kill_all_on_exit: {}", e);
|
||||
false
|
||||
|
|
@ -437,7 +426,7 @@ impl InitProcess {
|
|||
let bundle = self.bundle.to_string();
|
||||
let pid_path = Path::new(&bundle).join(INIT_PID_FILE);
|
||||
let mut create_opts = runc::options::CreateOpts::new()
|
||||
.pid_file(pid_path.to_owned())
|
||||
.pid_file(&pid_path)
|
||||
.no_pivot(self.no_pivot_root)
|
||||
.no_new_keyring(self.no_new_key_ring)
|
||||
.detach(false);
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ use std::path::Path;
|
|||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::Arc;
|
||||
|
||||
use containerd_shim as shim;
|
||||
|
||||
use log::{debug, error};
|
||||
|
||||
use containerd_shim as shim;
|
||||
use runc::options::{DeleteOpts, GlobalOpts, DEFAULT_COMMAND};
|
||||
use shim::api::*;
|
||||
use shim::error::{Error, Result};
|
||||
|
|
@ -73,7 +73,7 @@ impl Shim for Service {
|
|||
let (child_id, address) = spawn(opts, &grouping, Vec::new())?;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
crate::synchronous::cgroup::set_cgroup_and_oom_score(child_id)?;
|
||||
containerd_shim::cgroup::set_cgroup_and_oom_score(child_id)?;
|
||||
|
||||
write_address(&address)?;
|
||||
Ok(address)
|
||||
|
|
|
|||
|
|
@ -40,5 +40,8 @@ tokio = { version = "1.17.0", features = ["full"], optional = true }
|
|||
futures = {version = "0.3.21", optional = true}
|
||||
signal-hook-tokio = {version = "0.3.1", optional = true, features = ["futures-v0_3"]}
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
cgroups-rs = "0.2.9"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.0"
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ impl ConsoleSocket {
|
|||
}
|
||||
|
||||
// async drop is not supported yet, we can only call clean manually after socket received
|
||||
pub async fn clean(&self) {
|
||||
pub async fn clean(self) {
|
||||
if self.rmdir {
|
||||
if let Some(tmp_socket_dir) = self.path.parent() {
|
||||
tokio::fs::remove_dir_all(tmp_socket_dir)
|
||||
|
|
|
|||
|
|
@ -18,10 +18,14 @@ use std::collections::HashMap;
|
|||
|
||||
use async_trait::async_trait;
|
||||
use log::debug;
|
||||
use oci_spec::runtime::LinuxResources;
|
||||
use time::OffsetDateTime;
|
||||
use tokio::sync::oneshot::Receiver;
|
||||
|
||||
use containerd_shim_protos::api::{CreateTaskRequest, ExecProcessRequest, StateResponse};
|
||||
use containerd_shim_protos::api::{
|
||||
CreateTaskRequest, ExecProcessRequest, ProcessInfo, StateResponse,
|
||||
};
|
||||
use containerd_shim_protos::cgroups::metrics::Metrics;
|
||||
|
||||
use crate::asynchronous::processes::Process;
|
||||
use crate::error::Result;
|
||||
|
|
@ -45,6 +49,9 @@ pub trait Container {
|
|||
async fn resize_pty(&mut self, exec_id: Option<&str>, height: u32, width: u32) -> Result<()>;
|
||||
async fn pid(&self) -> i32;
|
||||
async fn id(&self) -> String;
|
||||
async fn update(&mut self, resources: &LinuxResources) -> Result<()>;
|
||||
async fn stats(&self) -> Result<Metrics>;
|
||||
async fn all_processes(&self) -> Result<Vec<ProcessInfo>>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
|
@ -154,6 +161,30 @@ where
|
|||
async fn id(&self) -> String {
|
||||
self.id.to_string()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn update(&mut self, resources: &LinuxResources) -> Result<()> {
|
||||
self.init.update(resources).await
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
async fn update(&mut self, _resources: &LinuxResources) -> Result<()> {
|
||||
Err(Error::Unimplemented("update".to_string()))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn stats(&self) -> Result<Metrics> {
|
||||
self.init.stats().await
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
async fn stats(&self) -> Result<Metrics> {
|
||||
Err(Error::Unimplemented("stats".to_string()))
|
||||
}
|
||||
|
||||
async fn all_processes(&self) -> Result<Vec<ProcessInfo>> {
|
||||
self.init.ps().await
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E, P> ContainerTemplate<T, E, P>
|
||||
|
|
|
|||
|
|
@ -98,16 +98,6 @@ where
|
|||
{
|
||||
if let Some(err) = bootstrap::<T>(runtime_id, opts).await.err() {
|
||||
eprintln!("{}: {:?}", runtime_id, err);
|
||||
let mut f = tokio::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.append(true)
|
||||
.open("/tmp/containerd-shim.log")
|
||||
.await
|
||||
.unwrap();
|
||||
f.write_all(format!("error bootstrap {}....\n", err).as_bytes())
|
||||
.await
|
||||
.unwrap();
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -122,7 +112,7 @@ where
|
|||
|
||||
let ttrpc_address = env::var(TTRPC_ADDRESS)?;
|
||||
// Create shim instance
|
||||
let mut config = opts.unwrap_or_else(Config::default);
|
||||
let mut config = opts.unwrap_or_default();
|
||||
|
||||
// Setup signals
|
||||
let signals = setup_signals_tokio(&config);
|
||||
|
|
@ -145,12 +135,13 @@ where
|
|||
};
|
||||
|
||||
let address = shim.start_shim(args).await?;
|
||||
|
||||
tokio::io::stdout()
|
||||
let mut stdout = tokio::io::stdout();
|
||||
stdout
|
||||
.write_all(address.as_bytes())
|
||||
.await
|
||||
.map_err(io_error!(e, "write stdout"))?;
|
||||
|
||||
// containerd occasionally read an empty string without flushing the stdout
|
||||
stdout.flush().await.map_err(io_error!(e, "flush stdout"))?;
|
||||
Ok(())
|
||||
}
|
||||
"delete" => {
|
||||
|
|
@ -290,14 +281,11 @@ pub async fn spawn(opts: StartOpts, grouping: &str, vars: Vec<(&str, &str)>) ->
|
|||
}
|
||||
command.envs(vars);
|
||||
|
||||
command
|
||||
.spawn()
|
||||
.map_err(io_error!(e, "spawn shim"))
|
||||
.map(|_| {
|
||||
// Ownership of `listener` has been passed to child.
|
||||
std::mem::forget(listener);
|
||||
address
|
||||
})
|
||||
let _child = command.spawn().map_err(io_error!(e, "spawn shim"))?;
|
||||
#[cfg(target_os = "linux")]
|
||||
crate::cgroup::set_cgroup_and_oom_score(_child.id())?;
|
||||
std::mem::forget(listener);
|
||||
Ok(address)
|
||||
}
|
||||
|
||||
fn setup_signals_tokio(config: &Config) -> Signals {
|
||||
|
|
@ -314,25 +302,29 @@ async fn handle_signals(signals: Signals) {
|
|||
match sig {
|
||||
SIGTERM | SIGINT => {
|
||||
debug!("received {}", sig);
|
||||
return;
|
||||
}
|
||||
SIGCHLD => {
|
||||
let mut status: c_int = 0;
|
||||
let options: c_int = libc::WNOHANG;
|
||||
let res_pid = asyncify(move || -> Result<pid_t> {
|
||||
Ok(unsafe { libc::waitpid(-1, &mut status, options) })
|
||||
SIGCHLD => loop {
|
||||
let result = asyncify(move || -> Result<(pid_t, c_int)> {
|
||||
let mut status: c_int = -1;
|
||||
let pid = unsafe { libc::waitpid(-1, &mut status, libc::WNOHANG) };
|
||||
if pid <= 0 {
|
||||
return Err(other!("wait finished"));
|
||||
}
|
||||
let status = libc::WEXITSTATUS(status);
|
||||
Ok((pid, status))
|
||||
})
|
||||
.await
|
||||
.unwrap_or(-1);
|
||||
let status = libc::WEXITSTATUS(status);
|
||||
if res_pid > 0 {
|
||||
.await;
|
||||
|
||||
if let Ok((res_pid, status)) = result {
|
||||
monitor_notify_by_pid(res_pid, status)
|
||||
.await
|
||||
.unwrap_or_else(|e| {
|
||||
error!("failed to send pid exit event {}", e);
|
||||
})
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,17 +15,19 @@
|
|||
*/
|
||||
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use oci_spec::runtime::LinuxResources;
|
||||
use time::OffsetDateTime;
|
||||
use tokio::sync::oneshot::{channel, Receiver, Sender};
|
||||
|
||||
use containerd_shim_protos::api::{StateResponse, Status};
|
||||
use containerd_shim_protos::api::{ProcessInfo, StateResponse, Status};
|
||||
use containerd_shim_protos::cgroups::metrics::Metrics;
|
||||
use containerd_shim_protos::protobuf::well_known_types::Timestamp;
|
||||
|
||||
use crate::io::Stdio;
|
||||
use crate::util::asyncify;
|
||||
use crate::Error;
|
||||
use crate::{ioctl_set_winsz, Console};
|
||||
|
||||
#[async_trait]
|
||||
|
|
@ -40,6 +42,9 @@ pub trait Process {
|
|||
async fn exit_code(&self) -> i32;
|
||||
async fn exited_at(&self) -> Option<OffsetDateTime>;
|
||||
async fn resize_pty(&mut self, height: u32, width: u32) -> crate::Result<()>;
|
||||
async fn update(&mut self, resources: &LinuxResources) -> crate::Result<()>;
|
||||
async fn stats(&self) -> crate::Result<Metrics>;
|
||||
async fn ps(&self) -> crate::Result<Vec<ProcessInfo>>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
|
@ -47,6 +52,9 @@ pub trait ProcessLifecycle<P: Process> {
|
|||
async fn start(&self, p: &mut P) -> crate::Result<()>;
|
||||
async fn kill(&self, p: &mut P, signal: u32, all: bool) -> crate::Result<()>;
|
||||
async fn delete(&self, p: &mut P) -> crate::Result<()>;
|
||||
async fn update(&self, p: &mut P, resources: &LinuxResources) -> crate::Result<()>;
|
||||
async fn stats(&self, p: &P) -> crate::Result<Metrics>;
|
||||
async fn ps(&self, p: &P) -> crate::Result<Vec<ProcessInfo>>;
|
||||
}
|
||||
|
||||
pub struct ProcessTemplate<S> {
|
||||
|
|
@ -58,16 +66,13 @@ pub struct ProcessTemplate<S> {
|
|||
pub exited_at: Option<OffsetDateTime>,
|
||||
pub wait_chan_tx: Vec<Sender<()>>,
|
||||
pub console: Option<Console>,
|
||||
pub lifecycle: S,
|
||||
pub lifecycle: Arc<S>,
|
||||
}
|
||||
|
||||
impl<S> ProcessTemplate<S>
|
||||
where
|
||||
S: Clone,
|
||||
{
|
||||
impl<S> ProcessTemplate<S> {
|
||||
pub fn new(id: &str, stdio: Stdio, lifecycle: S) -> Self {
|
||||
Self {
|
||||
state: Default::default(),
|
||||
state: Status::CREATED,
|
||||
id: id.to_string(),
|
||||
stdio,
|
||||
pid: 0,
|
||||
|
|
@ -75,7 +80,7 @@ where
|
|||
exited_at: None,
|
||||
wait_chan_tx: vec![],
|
||||
console: None,
|
||||
lifecycle,
|
||||
lifecycle: Arc::new(lifecycle),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -83,10 +88,10 @@ where
|
|||
#[async_trait]
|
||||
impl<S> Process for ProcessTemplate<S>
|
||||
where
|
||||
S: ProcessLifecycle<Self> + Clone + Sync + Send,
|
||||
S: ProcessLifecycle<Self> + Sync + Send,
|
||||
{
|
||||
async fn start(&mut self) -> crate::Result<()> {
|
||||
self.lifecycle.clone().start(&mut self).await?;
|
||||
self.lifecycle.clone().start(self).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -122,11 +127,11 @@ where
|
|||
}
|
||||
|
||||
async fn kill(&mut self, signal: u32, all: bool) -> crate::Result<()> {
|
||||
self.lifecycle.clone().kill(&mut self, signal, all).await
|
||||
self.lifecycle.clone().kill(self, signal, all).await
|
||||
}
|
||||
|
||||
async fn delete(&mut self) -> crate::Result<()> {
|
||||
self.lifecycle.clone().delete(&mut self).await
|
||||
self.lifecycle.clone().delete(self).await
|
||||
}
|
||||
|
||||
async fn wait_channel(&mut self) -> crate::Result<Receiver<()>> {
|
||||
|
|
@ -146,22 +151,31 @@ where
|
|||
}
|
||||
|
||||
async fn resize_pty(&mut self, height: u32, width: u32) -> crate::Result<()> {
|
||||
match self.console.as_ref() {
|
||||
Some(console) => unsafe {
|
||||
let w = libc::winsize {
|
||||
ws_row: height as u16,
|
||||
ws_col: width as u16,
|
||||
ws_xpixel: 0,
|
||||
ws_ypixel: 0,
|
||||
};
|
||||
let fd = console.file.as_raw_fd();
|
||||
asyncify(move || -> crate::Result<()> {
|
||||
ioctl_set_winsz(fd, &w).map(|_x| ()).map_err(Into::into)
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
},
|
||||
None => Err(other!("there is no console")),
|
||||
if let Some(console) = self.console.as_ref() {
|
||||
let w = libc::winsize {
|
||||
ws_row: height as u16,
|
||||
ws_col: width as u16,
|
||||
ws_xpixel: 0,
|
||||
ws_ypixel: 0,
|
||||
};
|
||||
let fd = console.file.as_raw_fd();
|
||||
asyncify(move || -> crate::Result<()> {
|
||||
unsafe { ioctl_set_winsz(fd, &w).map(|_x| ()).map_err(Into::into) }
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update(&mut self, resources: &LinuxResources) -> crate::Result<()> {
|
||||
self.lifecycle.clone().update(self, resources).await
|
||||
}
|
||||
|
||||
async fn stats(&self) -> crate::Result<Metrics> {
|
||||
self.lifecycle.stats(self).await
|
||||
}
|
||||
|
||||
async fn ps(&self) -> crate::Result<Vec<ProcessInfo>> {
|
||||
self.lifecycle.ps(self).await
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,14 @@ use std::sync::Arc;
|
|||
|
||||
use async_trait::async_trait;
|
||||
use log::{debug, info, warn};
|
||||
use oci_spec::runtime::LinuxResources;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
use tokio::sync::{MappedMutexGuard, Mutex, MutexGuard};
|
||||
|
||||
use containerd_shim_protos::api::DeleteResponse;
|
||||
use containerd_shim_protos::api::{
|
||||
CloseIORequest, ConnectRequest, ConnectResponse, DeleteResponse, PidsRequest, PidsResponse,
|
||||
StatsRequest, StatsResponse, UpdateTaskRequest,
|
||||
};
|
||||
use containerd_shim_protos::events::task::{
|
||||
TaskCreate, TaskDelete, TaskExecAdded, TaskExecStarted, TaskIO, TaskStart,
|
||||
};
|
||||
|
|
@ -39,7 +43,7 @@ use crate::api::{
|
|||
use crate::asynchronous::container::{Container, ContainerFactory};
|
||||
use crate::asynchronous::ExitSignal;
|
||||
use crate::event::Event;
|
||||
use crate::util::{convert_to_timestamp, AsOption};
|
||||
use crate::util::{convert_to_any, convert_to_timestamp, AsOption};
|
||||
use crate::TtrpcResult;
|
||||
|
||||
type EventSender = Sender<(String, Box<dyn Message>)>;
|
||||
|
|
@ -215,6 +219,17 @@ where
|
|||
Ok(resp)
|
||||
}
|
||||
|
||||
async fn pids(&self, _ctx: &TtrpcContext, req: PidsRequest) -> TtrpcResult<PidsResponse> {
|
||||
debug!("Pids request for {:?}", req);
|
||||
let container = self.get_container(req.get_id()).await?;
|
||||
let procs = container.all_processes().await?;
|
||||
debug!("Pids request for {:?} returns successfully", req);
|
||||
Ok(PidsResponse {
|
||||
processes: procs.into(),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
async fn kill(&self, _ctx: &TtrpcContext, req: KillRequest) -> TtrpcResult<Empty> {
|
||||
info!("Kill request for {:?}", req);
|
||||
let mut container = self.get_container(req.get_id()).await?;
|
||||
|
|
@ -253,6 +268,25 @@ where
|
|||
Ok(Empty::new())
|
||||
}
|
||||
|
||||
async fn close_io(&self, _ctx: &TtrpcContext, _req: CloseIORequest) -> TtrpcResult<Empty> {
|
||||
// TODO call close_io of container
|
||||
Ok(Empty::new())
|
||||
}
|
||||
|
||||
async fn update(&self, _ctx: &TtrpcContext, req: UpdateTaskRequest) -> TtrpcResult<Empty> {
|
||||
debug!("Update request for {:?}", req);
|
||||
let resources: LinuxResources = serde_json::from_slice(req.get_resources().get_value())
|
||||
.map_err(|e| {
|
||||
ttrpc::Error::RpcStatus(ttrpc::get_status(
|
||||
ttrpc::Code::INVALID_ARGUMENT,
|
||||
format!("failed to parse resource spec: {}", e),
|
||||
))
|
||||
})?;
|
||||
let mut container = self.get_container(req.get_id()).await?;
|
||||
container.update(&resources).await?;
|
||||
Ok(Empty::new())
|
||||
}
|
||||
|
||||
async fn wait(&self, _ctx: &TtrpcContext, req: WaitRequest) -> TtrpcResult<WaitResponse> {
|
||||
info!("Wait request for {:?}", req);
|
||||
let exec_id = req.exec_id.as_str().as_option();
|
||||
|
|
@ -283,6 +317,31 @@ where
|
|||
Ok(resp)
|
||||
}
|
||||
|
||||
async fn stats(&self, _ctx: &TtrpcContext, req: StatsRequest) -> TtrpcResult<StatsResponse> {
|
||||
debug!("Stats request for {:?}", req);
|
||||
let container = self.get_container(req.get_id()).await?;
|
||||
let stats = container.stats().await?;
|
||||
|
||||
let mut resp = StatsResponse::new();
|
||||
resp.set_stats(convert_to_any(Box::new(stats))?);
|
||||
Ok(resp)
|
||||
}
|
||||
|
||||
async fn connect(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
req: ConnectRequest,
|
||||
) -> TtrpcResult<ConnectResponse> {
|
||||
info!("Connect request for {:?}", req);
|
||||
let container = self.get_container(req.get_id()).await?;
|
||||
|
||||
Ok(ConnectResponse {
|
||||
shim_pid: std::process::id() as u32,
|
||||
task_pid: container.pid().await as u32,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
async fn shutdown(&self, _ctx: &TtrpcContext, _req: ShutdownRequest) -> TtrpcResult<Empty> {
|
||||
debug!("Shutdown request");
|
||||
let containers = self.containers.lock().await;
|
||||
|
|
|
|||
|
|
@ -24,15 +24,14 @@ use cgroups_rs::cgroup::get_cgroups_relative_paths_by_pid;
|
|||
use cgroups_rs::{hierarchies, Cgroup, CgroupPid, MaxValue, Subsystem};
|
||||
use oci_spec::runtime::LinuxResources;
|
||||
|
||||
use containerd_shim as shim;
|
||||
use containerd_shim::api::Options;
|
||||
use containerd_shim::protos::cgroups::metrics::{
|
||||
use containerd_shim_protos::cgroups::metrics::{
|
||||
CPUStat, CPUUsage, MemoryEntry, MemoryStat, Metrics,
|
||||
};
|
||||
use containerd_shim::protos::protobuf::well_known_types::Any;
|
||||
use containerd_shim::protos::protobuf::Message;
|
||||
use shim::error::{Error, Result};
|
||||
use shim::{io_error, other_error};
|
||||
use containerd_shim_protos::protobuf::well_known_types::Any;
|
||||
use containerd_shim_protos::protobuf::Message;
|
||||
use containerd_shim_protos::shim::oci::Options;
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
|
||||
// OOM_SCORE_ADJ_MAX is from https://github.com/torvalds/linux/blob/master/include/uapi/linux/oom.h#L10
|
||||
const OOM_SCORE_ADJ_MAX: i64 = 1000;
|
||||
|
|
@ -131,7 +130,7 @@ pub fn collect_metrics(pid: u32) -> Result<Metrics> {
|
|||
}
|
||||
|
||||
/// Update process cgroup limits
|
||||
pub fn update_metrics(pid: u32, resources: &LinuxResources) -> Result<()> {
|
||||
pub fn update_resources(pid: u32, resources: &LinuxResources) -> Result<()> {
|
||||
// get container main process cgroup
|
||||
let path =
|
||||
get_cgroups_relative_paths_by_pid(pid).map_err(other_error!(e, "get process cgroup"))?;
|
||||
|
|
@ -225,7 +224,7 @@ pub fn update_metrics(pid: u32, resources: &LinuxResources) -> Result<()> {
|
|||
mod tests {
|
||||
use cgroups_rs::{hierarchies, Cgroup, CgroupPid};
|
||||
|
||||
use crate::synchronous::cgroup::{
|
||||
use crate::cgroup::{
|
||||
add_task_to_cgroup, adjust_oom_score, read_process_oom_score, OOM_SCORE_ADJ_MAX,
|
||||
};
|
||||
|
||||
|
|
@ -39,8 +39,9 @@ use std::os::unix::io::RawFd;
|
|||
use std::os::unix::net::UnixListener;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub use containerd_shim_protos as protos;
|
||||
use nix::ioctl_write_ptr_bad;
|
||||
|
||||
pub use containerd_shim_protos as protos;
|
||||
pub use protos::shim::shim::DeleteResponse;
|
||||
pub use protos::ttrpc::{context::Context, Result as TtrpcResult};
|
||||
|
||||
|
|
@ -56,6 +57,7 @@ pub mod error;
|
|||
mod args;
|
||||
#[cfg(feature = "async")]
|
||||
pub mod asynchronous;
|
||||
pub mod cgroup;
|
||||
pub mod event;
|
||||
pub mod io;
|
||||
mod logger;
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ where
|
|||
let ttrpc_address = env::var(TTRPC_ADDRESS)?;
|
||||
|
||||
// Create shim instance
|
||||
let mut config = opts.unwrap_or_else(Config::default);
|
||||
let mut config = opts.unwrap_or_default();
|
||||
|
||||
// Setup signals
|
||||
let signals = setup_signals(&config);
|
||||
|
|
@ -228,7 +228,6 @@ fn handle_signals(mut signals: Signals) {
|
|||
match sig {
|
||||
SIGTERM | SIGINT => {
|
||||
debug!("received {}", sig);
|
||||
return;
|
||||
}
|
||||
SIGCHLD => loop {
|
||||
unsafe {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "1.54"
|
||||
channel = "1.59"
|
||||
components = ["rustfmt", "clippy"]
|
||||
|
|
|
|||
Loading…
Reference in New Issue