From f29e21ce67d4b599873de5591f8d2916ebdc49a7 Mon Sep 17 00:00:00 2001 From: Jorge Prendes Date: Thu, 23 Jan 2025 11:54:52 +0000 Subject: [PATCH] feed containerd-shim monitor during tests Signed-off-by: Jorge Prendes --- Cargo.lock | 1 + crates/containerd-shim-wasm/Cargo.toml | 3 ++ crates/containerd-shim-wasm/src/testing.rs | 54 +++++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index afa8f54a1..ea48d07e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -929,6 +929,7 @@ dependencies = [ "serde_bytes", "serde_json", "sha256", + "signal-hook", "temp-env", "tempfile", "thiserror 2.0.11", diff --git a/crates/containerd-shim-wasm/Cargo.toml b/crates/containerd-shim-wasm/Cargo.toml index 4f6dda883..2c2e12c54 100644 --- a/crates/containerd-shim-wasm/Cargo.toml +++ b/crates/containerd-shim-wasm/Cargo.toml @@ -18,6 +18,7 @@ containerd-shim = { workspace = true } containerd-shim-wasm-test-modules = { workspace = true, optional = true } oci-tar-builder = { workspace = true, optional = true } env_logger = { workspace = true, optional = true } +signal-hook = { version = "0.3", optional = true } git-version = { version = "0.3.9" } libc = { workspace = true } log = { workspace = true } @@ -94,12 +95,14 @@ tempfile = { workspace = true } oci-tar-builder = { workspace = true } rand = "0.8" temp-env = "0.3" +signal-hook = "0.3" [features] testing = [ "dep:containerd-shim-wasm-test-modules", "dep:env_logger", "dep:tempfile", + "dep:signal-hook", "dep:oci-tar-builder", ] opentelemetry = [ diff --git a/crates/containerd-shim-wasm/src/testing.rs b/crates/containerd-shim-wasm/src/testing.rs index 78bf02d4c..f98a3f328 100644 --- a/crates/containerd-shim-wasm/src/testing.rs +++ b/crates/containerd-shim-wasm/src/testing.rs @@ -9,15 +9,21 @@ use std::os::unix::fs::symlink; #[cfg(windows)] use std::os::windows::fs::symlink_file as symlink; use std::path::Path; +use std::sync::Once; use std::time::Duration; use anyhow::{bail, Result}; +use containerd_shim::monitor::monitor_notify_by_pid; pub use containerd_shim_wasm_test_modules as modules; -use libc::{SIGINT, SIGTERM}; +use libc::{SIGCHLD, SIGINT, SIGTERM}; +use nix::errno::Errno; +use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus}; +use nix::unistd::Pid; use oci_spec::runtime::{ get_default_namespaces, LinuxBuilder, LinuxNamespace, LinuxNamespaceType, ProcessBuilder, RootBuilder, SpecBuilder, }; +use signal_hook::iterator::Signals; use crate::sandbox::{Instance, InstanceConfig}; @@ -50,6 +56,9 @@ where pub fn new() -> Result { zygote::Zygote::init(); + // since we don't bootstrap containerd-shim, we need to feed it's monitor manually + setup_reaper(); + // start logging // to enable logging run `export RUST_LOG=trace` and append cargo command with // --show-output before running test @@ -310,6 +319,49 @@ where } } +fn setup_reaper() { + static SIGNALS: Once = Once::new(); + SIGNALS.call_once(|| { + // this is taken from containerd-shim's signal handler implementation + let mut signals = Signals::new([SIGCHLD]).expect("new signal failed"); + std::thread::spawn(move || { + loop { + for sig in signals.wait() { + match sig { + SIGCHLD => loop { + log::info!("SHIM HANDLING SIGCHLD"); + // Note that this thread sticks to child even it is suspended. + match waitpid(Some(Pid::from_raw(-1)), Some(WaitPidFlag::WNOHANG)) { + Ok(WaitStatus::Exited(pid, status)) => { + log::debug!("child {} terminated(status = {})", pid, status); + if let Err(e) = monitor_notify_by_pid(pid.as_raw(), status) { + log::error!("failed to send exit event {e}"); + } + } + Ok(WaitStatus::Signaled(pid, sig, _)) => { + log::debug!("child {} terminated(signal = {})", pid, sig); + if let Err(e) = + monitor_notify_by_pid(pid.as_raw(), 128 + sig as i32) + { + log::error!("failed to send signal event {}", e); + } + } + Ok(WaitStatus::StillAlive) => break, + Err(Errno::ECHILD) => break, + // stick until all children will be successfully waited, even some unexpected error occurs. + Err(e) => log::warn!("error occurred in signal handler: {}", e), + // stick until exit + _ => {} + } + }, + _ => { /* no-op */ } + } + } + } + }); + }); +} + pub mod oci_helpers { use std::fs::{write, File}; use std::process::{Command, Stdio};