1use std::path::PathBuf;
83
84use containerd_shim::{Config, parse, run};
85
86#[cfg(feature = "opentelemetry")]
87use crate::sandbox::async_utils::AmbientRuntime as _;
88#[cfg(feature = "opentelemetry")]
89use crate::sandbox::shim::{OtlpConfig, otel_traces_enabled};
90use crate::sandbox::{Instance, Shim};
91
92pub mod r#impl {
93 pub use git_version::git_version;
94}
95
96pub use crate::{revision, version};
97
98#[macro_export]
100macro_rules! version {
101 () => {
102 env!("CARGO_PKG_VERSION")
103 };
104}
105
106#[macro_export]
108macro_rules! revision {
109 () => {
110 match $crate::sandbox::cli::r#impl::git_version!(
111 args = ["--match=:", "--always", "--abbrev=15", "--dirty=.m"],
112 fallback = "",
113 ) {
114 "" => None,
115 version => Some(version),
116 }
117 };
118}
119
120#[cfg(target_os = "linux")]
121fn get_mem(pid: u32) -> (usize, usize) {
122 let mut rss = 0;
123 let mut total = 0;
124 for line in std::fs::read_to_string(format!("/proc/{pid}/status"))
125 .unwrap()
126 .lines()
127 {
128 let line = line.trim();
129 if let Some(rest) = line.strip_prefix("VmPeak:") {
133 if let Some(rest) = rest.strip_suffix("kB") {
134 total = rest.trim().parse().unwrap_or(0);
135 }
136 } else if let Some(rest) = line.strip_prefix("VmHWM:") {
137 if let Some(rest) = rest.strip_suffix("kB") {
138 rss = rest.trim().parse().unwrap_or(0);
139 }
140 }
141 }
142 (rss, total)
143}
144
145#[cfg(target_os = "linux")]
146fn log_mem() {
147 let pid = std::process::id();
148 let (rss, tot) = get_mem(pid);
149 log::info!("Shim peak memory usage was: peak resident set {rss} kB, peak total {tot} kB");
150
151 let pid = zygote::Zygote::global().run(|_| std::process::id(), ());
152 let (rss, tot) = get_mem(pid);
153 log::info!("Zygote peak memory usage was: peak resident set {rss} kB, peak total {tot} kB");
154}
155
156#[cfg(unix)]
157fn init_zygote_and_logger(debug: bool, config: &Config) {
158 zygote::Zygote::init();
159 if config.no_setup_logger {
160 return;
161 }
162 zygote::Zygote::global().run(
163 |(debug, default_log_level)| {
164 crate::vendor::containerd_shim::logger::init(debug, &default_log_level, "", "")
166 .expect("Failed to initialize logger");
167 },
168 (debug, config.default_log_level.clone()),
169 );
170}
171
172pub fn shim_main<'a, I>(
178 name: &str,
179 version: &str,
180 revision: impl Into<Option<&'a str>> + std::fmt::Debug,
181 shim_version: impl Into<Option<&'a str>> + std::fmt::Debug,
182 config: Option<Config>,
183) where
184 I: 'static + Instance + Sync + Send,
185{
186 let os_args: Vec<_> = std::env::args_os().collect();
188
189 let flags = parse(&os_args[1..]).unwrap();
190 let argv0 = PathBuf::from(&os_args[0]);
191 let argv0 = argv0.file_stem().unwrap_or_default().to_string_lossy();
192
193 if flags.version {
194 println!("{argv0}:");
195 println!(" Runtime: {name}");
196 println!(" Version: {version}");
197 println!(" Revision: {}", revision.into().unwrap_or("<none>"));
198 println!();
199
200 std::process::exit(0);
201 }
202
203 #[cfg(unix)]
205 {
206 let default_config = Config::default();
207 let config = config.as_ref().unwrap_or(&default_config);
208 init_zygote_and_logger(flags.debug, config);
209 }
210
211 #[cfg(feature = "opentelemetry")]
212 if otel_traces_enabled() {
213 async {
215 let otlp_config = OtlpConfig::build_from_env().expect("Failed to build OtelConfig.");
216 let _guard = otlp_config
217 .init()
218 .expect("Failed to initialize OpenTelemetry.");
219 tokio::task::block_in_place(move || {
220 shim_main_inner::<I>(name, shim_version, config);
221 });
222 }
223 .block_on();
224 } else {
225 shim_main_inner::<I>(name, shim_version, config);
226 }
227
228 #[cfg(not(feature = "opentelemetry"))]
229 {
230 shim_main_inner::<I>(name, shim_version, config);
231 }
232
233 #[cfg(target_os = "linux")]
234 log_mem();
235}
236
237#[cfg_attr(feature = "tracing", tracing::instrument(level = "Info"))]
238fn shim_main_inner<'a, I>(
239 name: &str,
240 shim_version: impl Into<Option<&'a str>> + std::fmt::Debug,
241 config: Option<Config>,
242) where
243 I: 'static + Instance + Sync + Send,
244{
245 #[cfg(feature = "opentelemetry")]
246 {
247 if let Ok(ctx) = std::env::var("TRACECONTEXT") {
249 OtlpConfig::set_trace_context(&ctx).unwrap();
250 } else {
251 let ctx = OtlpConfig::get_trace_context().unwrap();
252 unsafe {
256 std::env::set_var("TRACECONTEXT", ctx);
257 }
258 }
259 }
260
261 let shim_version = shim_version.into().unwrap_or("v1");
262 let lower_name = name.to_lowercase();
263 let shim_id = format!("io.containerd.{lower_name}.{shim_version}");
264
265 run::<Shim<I>>(&shim_id, config);
266}