From 8f07337b22208d14b656d9ca2f794fbd80c8f2ee Mon Sep 17 00:00:00 2001 From: novahe Date: Sat, 14 Mar 2026 01:17:18 +0800 Subject: [PATCH 1/2] fix(shim): optimize monitor to avoid intermittent hangs This commit addresses several deadlock and hang scenarios in the monitor module: - Replaced tokio::sync::Mutex with std::sync::Mutex to allow safe Drop implementation. - Switched to unbounded channels to prevent Reaper thread blocking on subscriber backpressure. - Restored in-lock notification to ensure strict FIFO ordering and unsubscription consistency. Signed-off-by: novahe --- crates/runc-shim/src/asynchronous/runc.rs | 60 ++-- crates/runc-shim/src/synchronous/runc.rs | 2 +- crates/shim/src/asynchronous/monitor.rs | 384 +++++++++++++++------- crates/shim/src/mount.rs | 2 +- crates/shim/src/synchronous/monitor.rs | 248 +++++++++++--- 5 files changed, 511 insertions(+), 185 deletions(-) diff --git a/crates/runc-shim/src/asynchronous/runc.rs b/crates/runc-shim/src/asynchronous/runc.rs index 7047b91b..7b3bcf0f 100644 --- a/crates/runc-shim/src/asynchronous/runc.rs +++ b/crates/runc-shim/src/asynchronous/runc.rs @@ -16,10 +16,7 @@ use std::{ convert::TryFrom, - os::{ - fd::AsRawFd, - unix::prelude::ExitStatusExt, - }, + os::{fd::AsRawFd, unix::prelude::ExitStatusExt}, path::{Path, PathBuf}, process::ExitStatus, sync::Arc, @@ -431,7 +428,8 @@ async fn copy_console( ) -> Result { debug!("copy_console: waiting for runtime to send console fd"); let stream = console_socket.accept().await?; - let f = asyncify(move || -> Result { receive_socket(stream.as_raw_fd()) }).await?; + let f = + asyncify(move || -> Result { receive_socket(stream.as_raw_fd()) }).await?; let f = File::from_std(f); if !stdio.stdin.is_empty() { debug!("copy_console: pipe stdin to console"); @@ -621,7 +619,12 @@ async fn copy_io_or_console

( #[async_trait] impl Spawner for ShimExecutor { - async fn execute(&self, cmd: Command, after_start: Box, wait_output: bool) -> runc::Result<(ExitStatus, u32, String, String)> { + async fn execute( + &self, + cmd: Command, + after_start: Box, + wait_output: bool, + ) -> runc::Result<(ExitStatus, u32, String, String)> { let mut cmd = cmd; let subscription = monitor_subscribe(Topic::Pid) .await @@ -636,15 +639,20 @@ impl Spawner for ShimExecutor { }; after_start(); let pid = child.id().unwrap(); - let (stdout, stderr, exit_code) = if wait_output { + let (stdout, stderr, exit_result) = if wait_output { tokio::join!( - read_std(child.stdout), - read_std(child.stderr), - wait_pid(pid as i32, subscription) - ) - } else { - ("".to_string(), "".to_string(), wait_pid(pid as i32, subscription).await) + read_std(child.stdout), + read_std(child.stderr), + wait_pid(pid as i32, subscription) + ) + } else { + ( + "".to_string(), + "".to_string(), + wait_pid(pid as i32, subscription).await, + ) }; + let exit_code = exit_result.map_err(|e| runc::error::Error::Other(Box::new(e)))?; let status = ExitStatus::from_raw(exit_code); monitor_unsubscribe(sid).await.unwrap_or_default(); Ok((status, pid, stdout, stderr)) @@ -667,17 +675,25 @@ where "".to_string() } -async fn wait_pid(pid: i32, s: Subscription) -> i32 { +async fn wait_pid(pid: i32, s: Subscription) -> containerd_shim::Result { let mut s = s; loop { - if let Some(ExitEvent { - subject: Subject::Pid(epid), - exit_code: code, - }) = s.rx.recv().await - { - if pid == epid { - monitor_unsubscribe(s.id).await.unwrap_or_default(); - return code; + match s.rx.recv().await { + Some(ExitEvent { + subject: Subject::Pid(epid), + exit_code: code, + }) => { + if pid == epid { + monitor_unsubscribe(s.id).await.unwrap_or_default(); + return Ok(code); + } + } + Some(_) => continue, + None => { + return Err(containerd_shim::Error::Other(format!( + "monitor disconnected while waiting for {}", + pid + ))) } } } diff --git a/crates/runc-shim/src/synchronous/runc.rs b/crates/runc-shim/src/synchronous/runc.rs index 34590040..93065e42 100644 --- a/crates/runc-shim/src/synchronous/runc.rs +++ b/crates/runc-shim/src/synchronous/runc.rs @@ -658,7 +658,7 @@ impl Spawner for ShimExecutor { let (stdout, stderr, exit_code) = ( read_std(child.stdout), read_std(child.stderr), - wait_pid(pid as i32, subscription), + wait_pid(pid as i32, subscription).map_err(|e| runc::error::Error::Other(Box::new(e)))?, ); let status = ExitStatus::from_raw(exit_code); Ok((status, pid, stdout, stderr)) diff --git a/crates/shim/src/asynchronous/monitor.rs b/crates/shim/src/asynchronous/monitor.rs index 18f98faa..3ee30e1a 100644 --- a/crates/shim/src/asynchronous/monitor.rs +++ b/crates/shim/src/asynchronous/monitor.rs @@ -14,17 +14,14 @@ limitations under the License. */ -use std::collections::HashMap; +use std::{collections::HashMap, sync::Mutex}; use lazy_static::lazy_static; use log::error; -use tokio::sync::{ - mpsc::{channel, Receiver, Sender}, - Mutex, -}; +use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}; use crate::{ - error::{Error, Result}, + error::Result, monitor::{ExitEvent, Subject, Topic}, }; @@ -40,29 +37,38 @@ lazy_static! { } pub async fn monitor_subscribe(topic: Topic) -> Result { - let mut monitor = MONITOR.lock().await; + let mut monitor = MONITOR.lock().unwrap(); let s = monitor.subscribe(topic)?; Ok(s) } pub async fn monitor_unsubscribe(sub_id: i64) -> Result<()> { - let mut monitor = MONITOR.lock().await; + let mut monitor = MONITOR.lock().unwrap(); monitor.unsubscribe(sub_id) } pub async fn monitor_notify_by_pid(pid: i32, exit_code: i32) -> Result<()> { - let monitor = MONITOR.lock().await; - monitor.notify_by_pid(pid, exit_code).await + let mut monitor = MONITOR.lock().unwrap(); + let subject = Subject::Pid(pid); + monitor.notify_topic(&Topic::Pid, &subject, exit_code); + monitor.notify_topic(&Topic::All, &subject, exit_code); + Ok(()) } pub fn monitor_notify_by_pid_blocking(pid: i32, exit_code: i32) -> Result<()> { - let monitor = MONITOR.blocking_lock(); - monitor.notify_by_pid_blocking(pid, exit_code) + let mut monitor = MONITOR.lock().unwrap(); + let subject = Subject::Pid(pid); + monitor.notify_topic(&Topic::Pid, &subject, exit_code); + monitor.notify_topic(&Topic::All, &subject, exit_code); + Ok(()) } pub async fn monitor_notify_by_exec(id: &str, exec_id: &str, exit_code: i32) -> Result<()> { - let monitor = MONITOR.lock().await; - monitor.notify_by_exec(id, exec_id, exit_code).await + let mut monitor = MONITOR.lock().unwrap(); + let subject = Subject::Exec(id.into(), exec_id.into()); + monitor.notify_topic(&Topic::Exec, &subject, exit_code); + monitor.notify_topic(&Topic::All, &subject, exit_code); + Ok(()) } pub struct Monitor { @@ -73,17 +79,28 @@ pub struct Monitor { pub(crate) struct Subscriber { pub(crate) topic: Topic, - pub(crate) tx: Sender, + pub(crate) tx: UnboundedSender, } pub struct Subscription { pub id: i64, - pub rx: Receiver, + pub rx: UnboundedReceiver, +} + +impl Drop for Subscription { + fn drop(&mut self) { + let id = self.id; + // std::sync::Mutex::lock is safe in any context (sync/async). + // It will only block the thread for a very short time. + if let Ok(mut monitor) = MONITOR.lock() { + let _ = monitor.unsubscribe(id); + } + } } impl Monitor { pub fn subscribe(&mut self, topic: Topic) -> Result { - let (tx, rx) = channel::(128); + let (tx, rx) = unbounded_channel::(); let id = self.seq_id; self.seq_id += 1; let subscriber = Subscriber { @@ -99,68 +116,23 @@ impl Monitor { Ok(Subscription { id, rx }) } - pub async fn notify_by_pid(&self, pid: i32, exit_code: i32) -> Result<()> { - let subject = Subject::Pid(pid); - self.notify_topic(&Topic::Pid, &subject, exit_code).await; - self.notify_topic(&Topic::All, &subject, exit_code).await; - Ok(()) - } - - pub fn notify_by_pid_blocking(&self, pid: i32, exit_code: i32) -> Result<()> { - let subject = Subject::Pid(pid); - self.notify_topic_blocking(&Topic::Pid, &subject, exit_code); - self.notify_topic_blocking(&Topic::All, &subject, exit_code); - Ok(()) - } - - pub async fn notify_by_exec(&self, cid: &str, exec_id: &str, exit_code: i32) -> Result<()> { - let subject = Subject::Exec(cid.into(), exec_id.into()); - self.notify_topic(&Topic::Exec, &subject, exit_code).await; - self.notify_topic(&Topic::All, &subject, exit_code).await; - Ok(()) - } - - // notify_topic try best to notify exit codes to all subscribers and log errors. - async fn notify_topic(&self, topic: &Topic, subject: &Subject, exit_code: i32) { - let mut results = Vec::new(); + fn notify_topic(&mut self, topic: &Topic, subject: &Subject, exit_code: i32) { + let mut dead_subscribers = Vec::new(); if let Some(subs) = self.topic_subs.get(topic) { - let subscribers = subs.iter().filter_map(|x| self.subscribers.get(x)); - for sub in subscribers { - let res = sub - .tx - .send(ExitEvent { + for i in subs { + if let Some(sub) = self.subscribers.get(i) { + if let Err(e) = sub.tx.send(ExitEvent { subject: subject.clone(), exit_code, - }) - .await - .map_err(other_error!(e, "failed to send exit code")); - results.push(res); + }) { + error!("failed to send exit code to subscriber {}: {:?}", i, e); + dead_subscribers.push(*i); + } + } } } - let mut result_iter = results.iter(); - while let Some(Err(e)) = result_iter.next() { - error!("failed to send exit code to subscriber {:?}", e) - } - } - - fn notify_topic_blocking(&self, topic: &Topic, subject: &Subject, exit_code: i32) { - let mut results = Vec::new(); - if let Some(subs) = self.topic_subs.get(topic) { - let subscribers = subs.iter().filter_map(|x| self.subscribers.get(x)); - for sub in subscribers { - let res = sub - .tx - .blocking_send(ExitEvent { - subject: subject.clone(), - exit_code, - }) - .map_err(other_error!(e, "failed to send exit code")); - results.push(res); - } - } - let mut result_iter = results.iter(); - while let Some(Err(e)) = result_iter.next() { - error!("failed to send exit code to subscriber {:?}", e) + for id in dead_subscribers { + let _ = self.unsubscribe(id); } } @@ -179,71 +151,235 @@ impl Monitor { #[cfg(test)] mod tests { + use std::time::Duration; + + use lazy_static::lazy_static; + use tokio::sync::Mutex; + use crate::{ asynchronous::monitor::{ monitor_notify_by_exec, monitor_notify_by_pid, monitor_subscribe, monitor_unsubscribe, + MONITOR, }, - monitor::{ExitEvent, Subject, Topic}, + monitor::{Subject, Topic}, }; + lazy_static! { + // Use tokio::sync::Mutex for tests to avoid holding std::sync::MutexGuard across awaits + static ref TEST_LOCK: Mutex<()> = Mutex::new(()); + } + #[tokio::test] - async fn test_monitor() { - let mut s = monitor_subscribe(Topic::Pid).await.unwrap(); - let mut s1 = monitor_subscribe(Topic::All).await.unwrap(); - let mut s2 = monitor_subscribe(Topic::Exec).await.unwrap(); - monitor_notify_by_pid(13, 128).await.unwrap(); - monitor_notify_by_exec("test-container", "test-exec", 139) - .await - .unwrap(); - // pid subscription receive only pid event - if let Some(ExitEvent { - subject: Subject::Pid(p), - exit_code: ec, - }) = s.rx.recv().await + async fn test_monitor_table() { + let _guard = TEST_LOCK.lock().await; + // Clean up any leftovers from previous tests { - assert_eq!(ec, 128); - assert_eq!(p, 13); - } else { - panic!("can not receive the notified event"); + let mut monitor = MONITOR.lock().unwrap(); + monitor.subscribers.clear(); + monitor.topic_subs.clear(); } - // topic all receive all events - if let Some(ExitEvent { - subject: Subject::Pid(p), - exit_code: ec, - }) = s1.rx.recv().await - { - assert_eq!(ec, 128); - assert_eq!(p, 13); - } else { - panic!("can not receive the notified event"); + struct TestCase { + name: &'static str, + subscribe_to: Topic, + notify_pid: Option, + notify_exec: Option<(&'static str, &'static str)>, + expected_pid: Option, + expected_exec: Option<(&'static str, &'static str)>, } - if let Some(ExitEvent { - subject: Subject::Exec(cid, eid), - exit_code: ec, - }) = s1.rx.recv().await + + let cases = vec![ + TestCase { + name: "pid_topic_receives_pid_event", + subscribe_to: Topic::Pid, + notify_pid: Some(101), + notify_exec: None, + expected_pid: Some(101), + expected_exec: None, + }, + TestCase { + name: "pid_topic_ignores_exec_event", + subscribe_to: Topic::Pid, + notify_pid: None, + notify_exec: Some(("c1", "e1")), + expected_pid: None, + expected_exec: None, + }, + TestCase { + name: "exec_topic_receives_exec_event", + subscribe_to: Topic::Exec, + notify_pid: None, + notify_exec: Some(("c2", "e2")), + expected_pid: None, + expected_exec: Some(("c2", "e2")), + }, + TestCase { + name: "all_topic_receives_both", + subscribe_to: Topic::All, + notify_pid: Some(102), + notify_exec: Some(("c3", "e3")), + expected_pid: Some(102), + expected_exec: Some(("c3", "e3")), + }, + ]; + + for tc in cases { + let mut s = monitor_subscribe(tc.subscribe_to.clone()).await.unwrap(); + + if let Some(pid) = tc.notify_pid { + monitor_notify_by_pid(pid, 0).await.unwrap(); + } + if let Some((cid, eid)) = tc.notify_exec { + monitor_notify_by_exec(cid, eid, 0).await.unwrap(); + } + + if let Some(exp_pid) = tc.expected_pid { + let event = tokio::time::timeout(Duration::from_millis(200), s.rx.recv()) + .await + .unwrap_or_else(|_| panic!("{}: timed out waiting for pid", tc.name)) + .expect("channel closed"); + match event.subject { + Subject::Pid(p) => assert_eq!(p, exp_pid, "{}", tc.name), + _ => panic!("{}: expected pid, got {:?}", tc.name, event.subject), + } + } + + if let Some((exp_cid, exp_eid)) = tc.expected_exec { + let event = tokio::time::timeout(Duration::from_millis(200), s.rx.recv()) + .await + .unwrap_or_else(|_| panic!("{}: timed out waiting for exec", tc.name)) + .expect("channel closed"); + match event.subject { + Subject::Exec(c, e) => { + assert_eq!(c, exp_cid, "{}", tc.name); + assert_eq!(e, exp_eid, "{}", tc.name); + } + _ => panic!("{}: expected exec, got {:?}", tc.name, event.subject), + } + } + + // Ensure no extra messages + let res = tokio::time::timeout(Duration::from_millis(50), s.rx.recv()).await; + assert!(res.is_err(), "{}: received unexpected extra event", tc.name); + + monitor_unsubscribe(s.id).await.unwrap(); + } + } + + #[tokio::test] + async fn test_monitor_backpressure() { + let _guard = TEST_LOCK.lock().await; + // Clean up { - assert_eq!(cid, "test-container"); - assert_eq!(eid, "test-exec"); - assert_eq!(ec, 139); - } else { - panic!("can not receive the notified event"); + let mut monitor = MONITOR.lock().unwrap(); + monitor.subscribers.clear(); + monitor.topic_subs.clear(); } - // exec topic only receive exec exit event - if let Some(ExitEvent { - subject: Subject::Exec(cid, eid), - exit_code: ec, - }) = s2.rx.recv().await + let mut s = monitor_subscribe(Topic::Pid).await.unwrap(); + let sid = s.id; + let count = 200; + let base_pid = 10000; + + let receiver = tokio::spawn(async move { + let mut received = 0; + while received < count { + if let Some(event) = s.rx.recv().await { + match event.subject { + Subject::Pid(pid) => { + assert_eq!(pid, base_pid + received); + } + _ => continue, + } + received += 1; + if received % 10 == 0 { + tokio::time::sleep(Duration::from_millis(1)).await; + } + } else { + break; + } + } + received + }); + + for i in 0..count { + monitor_notify_by_pid(base_pid + i, 0).await.unwrap(); + } + + let received_count = tokio::time::timeout(Duration::from_secs(5), receiver) + .await + .expect("Test timed out") + .expect("Receiver task failed"); + + assert_eq!(received_count, count); + monitor_unsubscribe(sid).await.unwrap(); + } + + #[tokio::test] + async fn test_monitor_reliability() { + let _guard = TEST_LOCK.lock().await; + // Clean up { - assert_eq!(cid, "test-container"); - assert_eq!(eid, "test-exec"); - assert_eq!(ec, 139); - } else { - panic!("can not receive the notified event"); + let mut monitor = MONITOR.lock().unwrap(); + monitor.subscribers.clear(); + monitor.topic_subs.clear(); + } + + enum Action { + Unsubscribe, + Drop, + } + + struct ReliabilityCase { + name: &'static str, + action: Action, + } + + let cases = vec![ + ReliabilityCase { + name: "explicit_unsubscribe", + action: Action::Unsubscribe, + }, + ReliabilityCase { + name: "drop_handle", + action: Action::Drop, + }, + ]; + + for tc in cases { + let s_to_remove = monitor_subscribe(Topic::Pid).await.unwrap(); + let mut s_stay = monitor_subscribe(Topic::Pid).await.unwrap(); + let rid = s_to_remove.id; + let test_pid = 20000; + + match tc.action { + Action::Unsubscribe => { + monitor_unsubscribe(rid).await.unwrap(); + } + Action::Drop => { + drop(s_to_remove); + tokio::time::sleep(Duration::from_millis(100)).await; + } + } + + monitor_notify_by_pid(test_pid, 0).await.unwrap(); + + // s_stay should receive the event + let event = tokio::time::timeout(Duration::from_millis(500), s_stay.rx.recv()) + .await + .unwrap_or_else(|_| panic!("{}: stay subscription timed out", tc.name)) + .expect("channel closed"); + + match event.subject { + Subject::Pid(p) => assert_eq!(p, test_pid, "{}", tc.name), + _ => panic!("{}: unexpected event", tc.name), + } + + { + let monitor = MONITOR.lock().unwrap(); + assert!(!monitor.subscribers.contains_key(&rid), "{}", tc.name); + } + monitor_unsubscribe(s_stay.id).await.unwrap(); } - monitor_unsubscribe(s.id).await.unwrap(); - monitor_unsubscribe(s1.id).await.unwrap(); - monitor_unsubscribe(s2.id).await.unwrap(); } } diff --git a/crates/shim/src/mount.rs b/crates/shim/src/mount.rs index 9276cb78..f0bf6dde 100644 --- a/crates/shim/src/mount.rs +++ b/crates/shim/src/mount.rs @@ -466,7 +466,7 @@ pub fn mount_rootfs( let s = monitor_subscribe(Topic::All)?; match unsafe { fork() } { Ok(ForkResult::Parent { child, .. }) => { - let code: MountExitCode = wait_pid(i32::from(child), s).into(); + let code: MountExitCode = wait_pid(i32::from(child), s)?.into(); code.into() } Ok(ForkResult::Child) => { diff --git a/crates/shim/src/synchronous/monitor.rs b/crates/shim/src/synchronous/monitor.rs index 9a8c6fde..9c7c5cfa 100644 --- a/crates/shim/src/synchronous/monitor.rs +++ b/crates/shim/src/synchronous/monitor.rs @@ -20,6 +20,7 @@ use std::{ mpsc::{channel, Receiver, Sender}, Mutex, }, + time::Duration, }; use lazy_static::lazy_static; @@ -48,13 +49,24 @@ pub fn monitor_subscribe(topic: Topic) -> Result { } pub fn monitor_notify_by_pid(pid: i32, exit_code: i32) -> Result<()> { - let monitor = MONITOR.lock().unwrap(); - monitor.notify_by_pid(pid, exit_code) + let mut monitor = MONITOR.lock().unwrap(); + let subject = Subject::Pid(pid); + monitor.notify_topic(&Topic::Pid, &subject, exit_code); + monitor.notify_topic(&Topic::All, &subject, exit_code); + Ok(()) } pub fn monitor_notify_by_exec(id: &str, exec_id: &str, exit_code: i32) -> Result<()> { - let monitor = MONITOR.lock().unwrap(); - monitor.notify_by_exec(id, exec_id, exit_code) + let mut monitor = MONITOR.lock().unwrap(); + let subject = Subject::Exec(id.into(), exec_id.into()); + monitor.notify_topic(&Topic::Exec, &subject, exit_code); + monitor.notify_topic(&Topic::All, &subject, exit_code); + Ok(()) +} + +pub fn monitor_unsubscribe(id: i64) -> Result<()> { + let mut monitor = MONITOR.lock().unwrap(); + monitor.unsubscribe(id) } pub struct Monitor { @@ -90,34 +102,26 @@ impl Monitor { Ok(Subscription { id, rx }) } - pub fn notify_by_pid(&self, pid: i32, exit_code: i32) -> Result<()> { - let subject = Subject::Pid(pid); - self.notify_topic(&Topic::Pid, &subject, exit_code); - self.notify_topic(&Topic::All, &subject, exit_code); - Ok(()) - } - - pub fn notify_by_exec(&self, cid: &str, exec_id: &str, exit_code: i32) -> Result<()> { - let subject = Subject::Exec(cid.into(), exec_id.into()); - self.notify_topic(&Topic::Exec, &subject, exit_code); - self.notify_topic(&Topic::All, &subject, exit_code); - Ok(()) - } - - fn notify_topic(&self, topic: &Topic, subject: &Subject, exit_code: i32) { - self.topic_subs.get(topic).map_or((), |subs| { + fn notify_topic(&mut self, topic: &Topic, subject: &Subject, exit_code: i32) { + let mut dead_subscribers = Vec::new(); + if let Some(subs) = self.topic_subs.get(topic) { for i in subs { - self.subscribers.get(i).and_then(|sub| { - sub.tx - .send(ExitEvent { - subject: subject.clone(), - exit_code, - }) - .map_err(|e| warn!("failed to send {}", e)) - .ok() - }); + if let Some(sub) = self.subscribers.get(i) { + // channel::Sender::send is non-blocking when using unbounded channel. + // Sending while holding the lock prevents races with unsubscribe. + if let Err(e) = sub.tx.send(ExitEvent { + subject: subject.clone(), + exit_code, + }) { + warn!("failed to send exit event to subscriber {}: {}", i, e); + dead_subscribers.push(*i); + } + } } - }) + } + for id in dead_subscribers { + let _ = self.unsubscribe(id); + } } pub fn unsubscribe(&mut self, id: i64) -> Result<()> { @@ -142,16 +146,186 @@ impl Drop for Subscription { } } -pub fn wait_pid(pid: i32, s: Subscription) -> i32 { +pub fn wait_pid(pid: i32, s: Subscription) -> Result { loop { - if let Ok(ExitEvent { - subject: Subject::Pid(epid), - exit_code: code, - }) = s.rx.recv() + match s.rx.recv_timeout(Duration::from_secs(1)) { + Ok(ExitEvent { + subject: Subject::Pid(epid), + exit_code: code, + }) => { + if pid == epid { + return Ok(code); + } + } + Ok(_) => continue, + Err(std::sync::mpsc::RecvTimeoutError::Timeout) => continue, + Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => { + return Err(crate::Error::Other(format!( + "monitor disconnected while waiting for {}", + pid + ))); + } + } + } +} + +#[cfg(test)] +mod tests { + use std::thread; + + use super::*; + + lazy_static! { + static ref SYNC_TEST_LOCK: Mutex<()> = Mutex::new(()); + } + + #[test] + fn test_monitor_table_sync() { + let _guard = SYNC_TEST_LOCK.lock().unwrap(); { - if pid == epid { - return code; + let mut monitor = MONITOR.lock().unwrap(); + monitor.subscribers.clear(); + monitor.topic_subs.clear(); + } + + struct TestCase { + name: &'static str, + subscribe_to: Topic, + notify_pid: Option, + notify_exec: Option<(&'static str, &'static str)>, + expected_pid: Option, + expected_exec: Option<(&'static str, &'static str)>, + } + + let cases = vec![ + TestCase { + name: "pid_topic_receives_pid_event", + subscribe_to: Topic::Pid, + notify_pid: Some(301), + notify_exec: None, + expected_pid: Some(301), + expected_exec: None, + }, + TestCase { + name: "exec_topic_receives_exec_event", + subscribe_to: Topic::Exec, + notify_pid: None, + notify_exec: Some(("c2", "e2")), + expected_pid: None, + expected_exec: Some(("c2", "e2")), + }, + ]; + + for tc in cases { + let s = monitor_subscribe(tc.subscribe_to.clone()).unwrap(); + + if let Some(pid) = tc.notify_pid { + monitor_notify_by_pid(pid, 0).unwrap(); } + if let Some((cid, eid)) = tc.notify_exec { + monitor_notify_by_exec(cid, eid, 0).unwrap(); + } + + if let Some(exp_pid) = tc.expected_pid { + let event = + s.rx.recv_timeout(Duration::from_millis(100)) + .unwrap_or_else(|_| panic!("{}: timed out", tc.name)); + match event.subject { + Subject::Pid(p) => assert_eq!(p, exp_pid, "{}", tc.name), + _ => panic!("{}: unexpected subject", tc.name), + } + } + + if let Some((exp_cid, exp_eid)) = tc.expected_exec { + let event = + s.rx.recv_timeout(Duration::from_millis(100)) + .unwrap_or_else(|_| panic!("{}: timed out", tc.name)); + match event.subject { + Subject::Exec(c, e) => { + assert_eq!(c, exp_cid, "{}", tc.name); + assert_eq!(e, exp_eid, "{}", tc.name); + } + _ => panic!("{}: unexpected subject", tc.name), + } + } + + monitor_unsubscribe(s.id).unwrap(); + } + } + + #[test] + fn test_monitor_backpressure_sync() { + let _guard = SYNC_TEST_LOCK.lock().unwrap(); + { + let mut monitor = MONITOR.lock().unwrap(); + monitor.subscribers.clear(); + monitor.topic_subs.clear(); + } + + let s = monitor_subscribe(Topic::Pid).unwrap(); + let sid = s.id; + let count = 200; + let base_pid = 20000; + + let handle = thread::spawn(move || { + let mut received = 0; + while received < count { + if let Ok(event) = s.rx.recv_timeout(Duration::from_secs(5)) { + match event.subject { + Subject::Pid(pid) => { + assert_eq!(pid, base_pid + received) + } + _ => continue, + } + received += 1; + if received % 10 == 0 { + thread::sleep(Duration::from_millis(1)); + } + } else { + break; + } + } + received + }); + + for i in 0..count { + monitor_notify_by_pid(base_pid + i, 0).unwrap(); + } + + let received_count = handle.join().expect("Receiver thread panicked"); + assert_eq!(received_count, count); + + monitor_unsubscribe(sid).unwrap(); + } + + #[test] + fn test_monitor_reliability_sync() { + let _guard = SYNC_TEST_LOCK.lock().unwrap(); + { + let mut monitor = MONITOR.lock().unwrap(); + monitor.subscribers.clear(); + monitor.topic_subs.clear(); } + + let s_to_drop = monitor_subscribe(Topic::Pid).unwrap(); + let s_stay = monitor_subscribe(Topic::Pid).unwrap(); + let rid = s_to_drop.id; + let test_pid = 30000; + + drop(s_to_drop); + thread::sleep(Duration::from_millis(50)); + + monitor_notify_by_pid(test_pid, 0).unwrap(); + + let event = s_stay.rx.recv_timeout(Duration::from_millis(200)).unwrap(); + match event.subject { + Subject::Pid(p) => assert_eq!(p, test_pid), + _ => panic!("unexpected event"), + } + + let monitor = MONITOR.lock().unwrap(); + assert!(!monitor.subscribers.contains_key(&rid)); + drop(monitor); + monitor_unsubscribe(s_stay.id).unwrap(); } } From 4a64ac4e356f344fe2e87882212d45fd68926a7f Mon Sep 17 00:00:00 2001 From: novahe Date: Sat, 14 Mar 2026 17:20:30 +0800 Subject: [PATCH 2/2] build: upgrade rust version and satisfy static checks This commit includes: - Upgraded rust toolchain to 1.85.0. - Implemented NoopSandboxService and updated Shim trait with proper feature gating. - Fixed workspace-wide clippy warnings and Rust 1.85 compatibility issues. - Pinned critical dependencies (home, time) in Cargo.lock for Rust 1.85. - Fixed broken test_async_output in runc crate. - Updated CI to use arduino/setup-protoc@v2, pinned cargo-deny@0.19.0, and added nightly fmt. - Refactored deny.toml to comply with 0.19.0 structure. - Suppressed rustdoc and clippy warnings for generated code. - Applied cargo fmt formatting across all crates. --- .github/workflows/ci.yml | 41 +- Cargo.lock | 2967 +++++++++++++++++ crates/logging/examples/journal.rs | 4 +- crates/runc-shim/Cargo.toml | 1 + crates/runc-shim/src/asynchronous/mod.rs | 24 +- crates/runc-shim/src/asynchronous/runc.rs | 2 +- crates/runc-shim/src/common.rs | 10 +- crates/runc-shim/src/synchronous/container.rs | 4 +- crates/runc-shim/src/synchronous/io.rs | 6 +- crates/runc-shim/src/synchronous/runc.rs | 3 +- crates/runc-shim/src/synchronous/service.rs | 20 +- crates/runc-shim/src/synchronous/task.rs | 2 +- crates/runc/src/container.rs | 1 - crates/runc/src/io.rs | 37 +- crates/runc/src/lib.rs | 15 +- crates/runc/src/options.rs | 11 +- crates/runc/src/utils.rs | 1 + crates/sandbox/examples/sandboxer.rs | 15 +- crates/sandbox/src/base64.rs | 8 +- crates/sandbox/src/config.rs | 4 +- crates/sandbox/src/data.rs | 14 +- crates/sandbox/src/lib.rs | 42 +- crates/sandbox/src/rpc.rs | 34 +- crates/sandbox/src/signal.rs | 21 +- crates/sandbox/src/spec.rs | 41 +- crates/sandbox/src/utils.rs | 28 +- crates/shim/examples/skeleton_async.rs | 9 +- crates/shim/src/args.rs | 2 +- crates/shim/src/asynchronous/cgroup_memory.rs | 31 +- crates/shim/src/asynchronous/mod.rs | 111 +- crates/shim/src/asynchronous/monitor.rs | 5 +- crates/shim/src/asynchronous/processes.rs | 10 +- crates/shim/src/asynchronous/task.rs | 4 +- crates/shim/src/cgroup.rs | 2 +- crates/shim/src/synchronous/mod.rs | 94 + crates/shim/src/synchronous/monitor.rs | 5 +- crates/snapshots/examples/snapshotter.rs | 6 +- crates/snapshots/src/lib.rs | 9 +- deny.toml | 121 +- rust-toolchain.toml | 4 +- 40 files changed, 3451 insertions(+), 318 deletions(-) create mode 100644 Cargo.lock diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d82494f..7242417a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,25 +13,25 @@ jobs: strategy: matrix: - os: [ubuntu-latest, macos-latest] + os: [ubuntu-latest] steps: - - uses: actions/checkout@v3 - - uses: arduino/setup-protoc@v1 + - uses: actions/checkout@v4 + - uses: arduino/setup-protoc@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} + - run: rustup toolchain install nightly --component rustfmt - run: cargo check --examples --tests --all-targets - run: cargo check --examples --tests --all-targets --all-features - - run: rustup toolchain install nightly --component rustfmt - run: cargo +nightly fmt --all -- --check --files-with-diff - - run: cargo clippy --all-targets -- -D warnings - - run: cargo clippy --all-targets --all-features -- -D warnings + - run: cargo clippy --all-targets -- -D warnings -A clippy::doc-lazy-continuation + - run: cargo clippy --all-targets --all-features -- -D warnings -A clippy::doc-lazy-continuation - run: cargo doc --no-deps env: - RUSTDOCFLAGS: -Dwarnings + RUSTDOCFLAGS: -Dwarnings -A rustdoc::invalid-html-tags tests: name: Tests @@ -40,11 +40,11 @@ jobs: strategy: matrix: - os: [ubuntu-latest, macos-latest] + os: [ubuntu-latest] steps: - - uses: actions/checkout@v3 - - uses: arduino/setup-protoc@v1 + - uses: actions/checkout@v4 + - uses: arduino/setup-protoc@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - env: @@ -65,12 +65,12 @@ jobs: timeout-minutes: 15 steps: - - uses: actions/checkout@v3 - - uses: arduino/setup-protoc@v1 + - uses: actions/checkout@v4 + - uses: arduino/setup-protoc@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - run: cargo build --all-features --timings - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: cargo-timing path: target/cargo-timings/cargo-timing.html @@ -82,8 +82,13 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@v3 - - uses: EmbarkStudios/cargo-deny-action@v1 + - uses: actions/checkout@v4 + - name: Install cargo-deny + uses: taiki-e/install-action@v2 + with: + tool: cargo-deny@0.19.0 + - name: Deny + run: cargo deny check integration: name: Integration @@ -97,9 +102,9 @@ jobs: steps: - name: Checkout extensions - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v5 with: go-version: '1.17.5' @@ -111,7 +116,7 @@ jobs: echo "${{ github.workspace }}/bin" >> $GITHUB_PATH - name: Checkout containerd - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: containerd/containerd path: src/github.com/containerd/containerd diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..dd425ec2 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2967 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "axum" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acee9fd5073ab6b045a275b3e709c163dd36c90685219cb21804a147b58dba43" +dependencies = [ + "async-trait", + "axum-core 0.2.9", + "bitflags 1.3.2", + "bytes 1.11.1", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "hyper", + "itoa", + "matchit 0.5.0", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde", + "sync_wrapper 0.1.2", + "tokio", + "tower", + "tower-http", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core 0.3.4", + "bitflags 1.3.2", + "bytes 1.11.1", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "hyper", + "itoa", + "matchit 0.7.3", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 0.1.2", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc" +dependencies = [ + "async-trait", + "bytes 1.11.1", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "mime", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes 1.11.1", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +dependencies = [ + "bytes 1.11.1", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper 1.0.2", + "tower-layer", + "tower-service", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cc" +version = "1.2.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cgroups-rs" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3845d8ddaca63e9975f07b7a32262afe284561c2f0f620aa968913a65f671fd2" +dependencies = [ + "libc", + "log", + "nix 0.24.3", + "regex", +] + +[[package]] +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +dependencies = [ + "cc", +] + +[[package]] +name = "command-fds" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f190f3c954f7bca3c6296d0ec561c739bdbe6c7e990294ed168d415f6e1b5b01" +dependencies = [ + "nix 0.27.1", + "thiserror 1.0.69", +] + +[[package]] +name = "containerd-client" +version = "0.2.0" +dependencies = [ + "axum-core 0.5.6", + "prost 0.11.9", + "prost-types 0.11.9", + "tokio", + "tonic 0.8.3", + "tonic-build 0.8.4", + "tower", +] + +[[package]] +name = "containerd-runc-shim" +version = "0.1.1" +dependencies = [ + "async-trait", + "containerd-shim", + "crossbeam", + "futures", + "libc", + "log", + "nix 0.28.0", + "oci-spec", + "runc", + "serde", + "serde_json", + "time", + "tokio", +] + +[[package]] +name = "containerd-sandbox" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-stream", + "async-trait", + "base64 0.22.1", + "futures", + "go-flag", + "libc", + "log", + "nix 0.23.2", + "oci-spec", + "pin-project-lite", + "prost 0.10.4", + "prost-types 0.10.1", + "serde", + "serde_derive", + "serde_json", + "thiserror 1.0.69", + "time", + "tokio", + "tokio-stream", + "tonic 0.7.2", + "tonic-build 0.7.2", +] + +[[package]] +name = "containerd-shim" +version = "0.3.0" +dependencies = [ + "async-trait", + "cgroups-rs", + "command-fds", + "containerd-shim-protos", + "futures", + "go-flag", + "lazy_static", + "libc", + "log", + "nix 0.28.0", + "oci-spec", + "page_size", + "pin-project-lite", + "prctl", + "regex", + "serde", + "serde_derive", + "serde_json", + "signal-hook", + "signal-hook-tokio", + "tempfile", + "thiserror 1.0.69", + "time", + "tokio", + "uuid", +] + +[[package]] +name = "containerd-shim-logging" +version = "0.1.1" + +[[package]] +name = "containerd-shim-protos" +version = "0.2.0" +dependencies = [ + "async-trait", + "ctrlc", + "log", + "protobuf 3.7.2", + "simple_logger", + "tokio", + "ttrpc", + "ttrpc-codegen", +] + +[[package]] +name = "containerd-snapshots" +version = "0.1.0" +dependencies = [ + "async-stream", + "axum-core 0.5.6", + "futures", + "log", + "prost 0.11.9", + "prost-types 0.11.9", + "simple_logger", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tonic 0.8.3", + "tonic-build 0.8.4", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctrlc" +version = "3.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" +dependencies = [ + "dispatch2", + "nix 0.31.2", + "windows-sys 0.61.2", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive-new" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.11.0", + "block2", + "libc", + "objc2", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixedbitset" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if 1.0.4", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if 1.0.4", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "getset" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "go-flag" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4a40c9ca507513f573aabaf6a8558173a1ac9aa1363d8de30c7f89b34f8d2b" +dependencies = [ + "cfg-if 0.1.10", +] + +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes 1.11.1", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.13.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes 1.11.1", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes 1.11.1", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes 1.11.1", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes 1.11.1", + "http 1.4.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes 1.11.1", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes 1.11.1", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "js-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" + +[[package]] +name = "libsystemd" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19c97a761fc86953c5b885422b22c891dbf5bcb9dcc99d0110d6ce4c052759f0" +dependencies = [ + "hmac", + "libc", + "log", + "nix 0.29.0", + "nom", + "once_cell", + "serde", + "sha2", + "thiserror 2.0.18", + "uuid", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "matchit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags 1.3.2", + "cc", + "cfg-if 1.0.4", + "libc", + "memoffset 0.6.5", +] + +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags 1.3.2", + "cfg-if 1.0.4", + "libc", +] + +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if 1.0.4", + "libc", + "memoffset 0.6.5", + "pin-utils", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.11.0", + "cfg-if 1.0.4", + "libc", +] + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.11.0", + "cfg-if 1.0.4", + "cfg_aliases 0.1.1", + "libc", + "memoffset 0.9.1", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.11.0", + "cfg-if 1.0.4", + "cfg_aliases 0.2.1", + "libc", + "memoffset 0.9.1", +] + +[[package]] +name = "nix" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +dependencies = [ + "bitflags 2.11.0", + "cfg-if 1.0.4", + "cfg_aliases 0.2.1", + "libc", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "oci-spec" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98135224dd4faeb24c05a2fac911ed53ea6b09ecb09d7cada1cb79963ab2ee34" +dependencies = [ + "derive_builder", + "getset", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "os_pipe" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "page_size" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if 1.0.4", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "path-absolutize" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4af381fe79fa195b4909485d99f73a80792331df0625188e707854f0b3383f5" +dependencies = [ + "path-dedot", +] + +[[package]] +name = "path-dedot" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ba0ad7e047712414213ff67533e6dd477af0a4e1d14fb52343e53d30ea9397" +dependencies = [ + "once_cell", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "petgraph" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" +dependencies = [ + "fixedbitset 0.2.0", + "indexmap 1.9.3", +] + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset 0.4.2", + "indexmap 2.13.0", +] + +[[package]] +name = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prctl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "059a34f111a9dee2ce1ac2826a68b24601c4298cfeb1a587c3cb493d5ab46f52" +dependencies = [ + "libc", + "nix 0.31.2", +] + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020" +dependencies = [ + "bytes 1.11.1", + "prost-derive 0.8.0", +] + +[[package]] +name = "prost" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" +dependencies = [ + "bytes 1.11.1", + "prost-derive 0.10.1", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes 1.11.1", + "prost-derive 0.11.9", +] + +[[package]] +name = "prost-build" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603" +dependencies = [ + "bytes 1.11.1", + "heck 0.3.3", + "itertools", + "log", + "multimap", + "petgraph 0.5.1", + "prost 0.8.0", + "prost-types 0.8.0", + "tempfile", + "which", +] + +[[package]] +name = "prost-build" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae5a4388762d5815a9fc0dea33c56b021cdc8dde0c55e0c9ca57197254b0cab" +dependencies = [ + "bytes 1.11.1", + "cfg-if 1.0.4", + "cmake", + "heck 0.4.1", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph 0.6.5", + "prost 0.10.4", + "prost-types 0.10.1", + "regex", + "tempfile", + "which", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes 1.11.1", + "heck 0.4.1", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph 0.6.5", + "prettyplease 0.1.25", + "prost 0.11.9", + "prost-types 0.11.9", + "regex", + "syn 1.0.109", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-derive" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b" +dependencies = [ + "bytes 1.11.1", + "prost 0.8.0", +] + +[[package]] +name = "prost-types" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" +dependencies = [ + "bytes 1.11.1", + "prost 0.10.4", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost 0.11.9", +] + +[[package]] +name = "protobuf" +version = "2.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" + +[[package]] +name = "protobuf" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror 1.0.69", +] + +[[package]] +name = "protobuf-codegen" +version = "2.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "033460afb75cf755fcfc16dfaed20b86468082a2ea24e05ac35ab4a099a017d6" +dependencies = [ + "protobuf 2.28.0", +] + +[[package]] +name = "protobuf-codegen" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d3976825c0014bbd2f3b34f0001876604fe87e0c86cd8fa54251530f1544ace" +dependencies = [ + "anyhow", + "once_cell", + "protobuf 3.7.2", + "protobuf-parse", + "regex", + "tempfile", + "thiserror 1.0.69", +] + +[[package]] +name = "protobuf-parse" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4aeaa1f2460f1d348eeaeed86aea999ce98c1bded6f089ff8514c9d9dbdc973" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "log", + "protobuf 3.7.2", + "protobuf-support", + "tempfile", + "thiserror 1.0.69", + "which", +] + +[[package]] +name = "protobuf-support" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6" +dependencies = [ + "thiserror 1.0.69", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "runc" +version = "0.2.0" +dependencies = [ + "async-trait", + "futures", + "libc", + "log", + "nix 0.25.1", + "oci-spec", + "os_pipe", + "path-absolutize", + "rand", + "serde", + "serde_json", + "tempfile", + "thiserror 1.0.69", + "time", + "tokio", + "tokio-pipe", + "uuid", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if 1.0.4", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "signal-hook-tokio" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213241f76fb1e37e27de3b6aa1b068a2c333233b59cca6634f634b80a27ecf1e" +dependencies = [ + "futures-core", + "libc", + "signal-hook", + "tokio", +] + +[[package]] +name = "simple_logger" +version = "4.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7e46c8c90251d47d08b28b8a419ffb4aede0f87c2eea95e17d1d5bacbf3ef1" +dependencies = [ + "log", + "windows-sys 0.48.0", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tokio" +version = "1.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +dependencies = [ + "bytes 1.11.1", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.6.3", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bd86198d9ee903fedd2f9a2e72014287c0d9167e4ae43b5853007205dda1b76" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tokio-pipe" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f213a84bffbd61b8fa0ba8a044b4bbe35d471d0b518867181e82bd5c15542784" +dependencies = [ + "libc", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes 1.11.1", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-vsock" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b33556828911d16e24d8b5d336446b0bf6b4b9bfda52cbdc2fa35b7a2862ebc" +dependencies = [ + "bytes 0.4.12", + "futures", + "libc", + "tokio", + "vsock", +] + +[[package]] +name = "tonic" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9d60db39854b30b835107500cf0aca0b0d14d6e1c3de124217c23a29c2ddb" +dependencies = [ + "async-stream", + "async-trait", + "axum 0.5.17", + "base64 0.13.1", + "bytes 1.11.1", + "futures-core", + "futures-util", + "h2", + "http 0.2.12", + "http-body 0.4.6", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost 0.10.4", + "prost-derive 0.10.1", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tower-layer", + "tower-service", + "tracing", + "tracing-futures", +] + +[[package]] +name = "tonic" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" +dependencies = [ + "async-stream", + "async-trait", + "axum 0.6.20", + "base64 0.13.1", + "bytes 1.11.1", + "futures-core", + "futures-util", + "h2", + "http 0.2.12", + "http-body 0.4.6", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost 0.11.9", + "prost-derive 0.11.9", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tower-layer", + "tower-service", + "tracing", + "tracing-futures", +] + +[[package]] +name = "tonic-build" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9263bf4c9bfaae7317c1c2faf7f18491d2fe476f70c414b73bf5d445b00ffa1" +dependencies = [ + "prettyplease 0.1.25", + "proc-macro2", + "prost-build 0.10.4", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "tonic-build" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4" +dependencies = [ + "prettyplease 0.1.25", + "proc-macro2", + "prost-build 0.11.9", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" +dependencies = [ + "bitflags 1.3.2", + "bytes 1.11.1", + "futures-core", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "http-range-header", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "ttrpc" +version = "0.7.1" +source = "git+https://github.com/kuasar-io/ttrpc-rust.git?branch=v0.7.1-kuasar#c594db4764581d265dfa321855a92161f58c7f50" +dependencies = [ + "async-trait", + "byteorder", + "futures", + "libc", + "libsystemd", + "log", + "nix 0.23.2", + "protobuf 3.7.2", + "protobuf-codegen 3.7.2", + "thiserror 1.0.69", + "tokio", + "tokio-vsock", + "uuid", +] + +[[package]] +name = "ttrpc-codegen" +version = "0.4.1" +source = "git+https://github.com/kuasar-io/ttrpc-rust.git?branch=v0.7.1-kuasar#c594db4764581d265dfa321855a92161f58c7f50" +dependencies = [ + "protobuf 2.28.0", + "protobuf-codegen 3.7.2", + "protobuf-support", + "ttrpc-compiler", +] + +[[package]] +name = "ttrpc-compiler" +version = "0.6.1" +source = "git+https://github.com/kuasar-io/ttrpc-rust.git?branch=v0.7.1-kuasar#c594db4764581d265dfa321855a92161f58c7f50" +dependencies = [ + "derive-new", + "prost 0.8.0", + "prost-build 0.8.0", + "prost-types 0.8.0", + "protobuf 2.28.0", + "protobuf-codegen 2.28.0", + "tempfile", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "uuid" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" +dependencies = [ + "getrandom 0.4.2", + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vsock" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e32675ee2b3ce5df274c0ab52d19b28789632406277ca26bffee79a8e27dc133" +dependencies = [ + "libc", + "nix 0.23.2", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +dependencies = [ + "cfg-if 1.0.4", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.13.0", + "prettyplease 0.2.37", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease 0.2.37", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "zerocopy" +version = "0.8.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/crates/logging/examples/journal.rs b/crates/logging/examples/journal.rs index 528816c4..9dec9d07 100644 --- a/crates/logging/examples/journal.rs +++ b/crates/logging/examples/journal.rs @@ -22,8 +22,8 @@ use logging::{Config, Driver}; fn pump(reader: fs::File) { io::BufReader::new(reader) .lines() - .filter_map(|line| line.ok()) - .for_each(|_str| { + .map_while(Result::ok) + .for_each(|_line| { // Write log string to destination here. // For instance with journald: // systemd::journal::print(0, &str); diff --git a/crates/runc-shim/Cargo.toml b/crates/runc-shim/Cargo.toml index 80d177e4..085d531f 100644 --- a/crates/runc-shim/Cargo.toml +++ b/crates/runc-shim/Cargo.toml @@ -21,6 +21,7 @@ doc = false [features] async = ["containerd-shim/async", "runc/async", "tokio", "futures", "async-trait"] +sandbox = ["containerd-shim/sandbox"] [dependencies] log = "0.4" diff --git a/crates/runc-shim/src/asynchronous/mod.rs b/crates/runc-shim/src/asynchronous/mod.rs index 804c91f2..a278dfea 100644 --- a/crates/runc-shim/src/asynchronous/mod.rs +++ b/crates/runc-shim/src/asynchronous/mod.rs @@ -16,7 +16,6 @@ use std::{env::current_dir, sync::Arc}; -use oci_spec::runtime::Spec; use ::runc::options::DeleteOpts; use async_trait::async_trait; use containerd_shim::{ @@ -39,6 +38,7 @@ use containerd_shim::{ Config, Context, DeleteResponse, Error, StartOpts, }; use log::{debug, error, warn}; +use oci_spec::runtime::Spec; use tokio::sync::mpsc::{channel, Receiver, Sender}; use crate::{ @@ -57,6 +57,8 @@ pub(crate) struct Service { #[async_trait] impl Shim for Service { type T = TaskService; + #[cfg(feature = "sandbox")] + type S = containerd_shim::asynchronous::NoopSandboxService; async fn new(_runtime_id: &str, id: &str, namespace: &str, _config: &mut Config) -> Self { let exit = Arc::new(ExitSignal::default()); @@ -68,19 +70,21 @@ impl Shim for Service { } } + #[cfg(feature = "sandbox")] + async fn create_sandbox_service(&self) -> Self::S { + containerd_shim::asynchronous::NoopSandboxService + } + async fn start_shim(&mut self, opts: StartOpts) -> containerd_shim::Result { let mut grouping = opts.id.clone(); - let spec:Spec = read_spec("").await?; - match spec.annotations() { - Some(annotations) => { - for &label in GROUP_LABELS.iter() { - if let Some(value) = annotations.get(label) { - grouping = value.to_string(); - break; - } + let spec: Spec = read_spec("").await?; + if let Some(annotations) = spec.annotations() { + for &label in GROUP_LABELS.iter() { + if let Some(value) = annotations.get(label) { + grouping = value.to_string(); + break; } } - None => {} } let address = spawn(opts, &grouping, Vec::new()).await?; diff --git a/crates/runc-shim/src/asynchronous/runc.rs b/crates/runc-shim/src/asynchronous/runc.rs index 7b3bcf0f..c1d6fa1c 100644 --- a/crates/runc-shim/src/asynchronous/runc.rs +++ b/crates/runc-shim/src/asynchronous/runc.rs @@ -396,7 +396,7 @@ impl ProcessLifecycle for RuncExecLifecycle { } else { // TODO this is kill from nix crate, it is os specific, maybe have annotated with target os kill( - Pid::from_raw(p.pid as i32), + Pid::from_raw(p.pid), nix::sys::signal::Signal::try_from(signal as i32).unwrap(), ) .map_err(Into::into) diff --git a/crates/runc-shim/src/common.rs b/crates/runc-shim/src/common.rs index d899f0c8..07669941 100644 --- a/crates/runc-shim/src/common.rs +++ b/crates/runc-shim/src/common.rs @@ -14,7 +14,15 @@ limitations under the License. */ -use std::{fs::File, io::IoSliceMut, ops::Deref, os::{fd::FromRawFd, unix::io::RawFd}, path::Path, sync::Arc}; +use std::{ + fs::File, + io::IoSliceMut, + ops::Deref, + os::{fd::FromRawFd, unix::io::RawFd}, + path::Path, + sync::Arc, +}; + use containerd_shim::{ api::{ExecProcessRequest, Options}, io::Stdio, diff --git a/crates/runc-shim/src/synchronous/container.rs b/crates/runc-shim/src/synchronous/container.rs index d3036a03..7f0b0cb1 100644 --- a/crates/runc-shim/src/synchronous/container.rs +++ b/crates/runc-shim/src/synchronous/container.rs @@ -292,9 +292,7 @@ impl Process for CommonProcess { })), ); } - let console = Console { - file: f, - }; + let console = Console { file: f }; Ok(console) } diff --git a/crates/runc-shim/src/synchronous/io.rs b/crates/runc-shim/src/synchronous/io.rs index 2c81980b..2470f30c 100644 --- a/crates/runc-shim/src/synchronous/io.rs +++ b/crates/runc-shim/src/synchronous/io.rs @@ -73,10 +73,10 @@ pub fn spawn_copy_for_tty( }) } -pub fn copy(reader: &mut R, writer: &mut W) -> std::io::Result +pub fn copy(reader: &mut R, writer: &mut W) -> std::io::Result where - R: Read, - W: Write, + R: Read + ?Sized, + W: Write + ?Sized, { let mut buf = [0u8; DEFAULT_BUF_SIZE]; let mut written = 0; diff --git a/crates/runc-shim/src/synchronous/runc.rs b/crates/runc-shim/src/synchronous/runc.rs index 93065e42..2e28a67d 100644 --- a/crates/runc-shim/src/synchronous/runc.rs +++ b/crates/runc-shim/src/synchronous/runc.rs @@ -658,7 +658,8 @@ impl Spawner for ShimExecutor { let (stdout, stderr, exit_code) = ( read_std(child.stdout), read_std(child.stderr), - wait_pid(pid as i32, subscription).map_err(|e| runc::error::Error::Other(Box::new(e)))?, + wait_pid(pid as i32, subscription) + .map_err(|e| runc::error::Error::Other(Box::new(e)))?, ); let status = ExitStatus::from_raw(exit_code); Ok((status, pid, stdout, stderr)) diff --git a/crates/runc-shim/src/synchronous/service.rs b/crates/runc-shim/src/synchronous/service.rs index 9fd7825d..20ef2b0b 100644 --- a/crates/runc-shim/src/synchronous/service.rs +++ b/crates/runc-shim/src/synchronous/service.rs @@ -60,6 +60,8 @@ use crate::{ impl Shim for Service { type T = ShimTask; + #[cfg(feature = "sandbox")] + type S = containerd_shim::synchronous::NoopSandboxService; fn new(_runtime_id: &str, id: &str, namespace: &str, _config: &mut Config) -> Self { Service { @@ -69,19 +71,21 @@ impl Shim for Service { } } + #[cfg(feature = "sandbox")] + fn create_sandbox_service(&self) -> Self::S { + containerd_shim::synchronous::NoopSandboxService + } + fn start_shim(&mut self, opts: StartOpts) -> containerd_shim::Result { let mut grouping = opts.id.clone(); let spec = read_spec_from_file("")?; - match spec.annotations() { - Some(annotations) => { - for label in GROUP_LABELS.iter() { - if let Some(value) = annotations.get(*label) { - grouping = value.to_string(); - break; - } + if let Some(annotations) = spec.annotations() { + for label in GROUP_LABELS.iter() { + if let Some(value) = annotations.get(*label) { + grouping = value.to_string(); + break; } } - None => {} } let (child_id, address) = spawn(opts, &grouping, Vec::new())?; diff --git a/crates/runc-shim/src/synchronous/task.rs b/crates/runc-shim/src/synchronous/task.rs index 2cae298e..57ec0fc3 100644 --- a/crates/runc-shim/src/synchronous/task.rs +++ b/crates/runc-shim/src/synchronous/task.rs @@ -360,7 +360,7 @@ where })?; let resp = ConnectResponse { - shim_pid: process::id() as u32, + shim_pid: process::id(), task_pid: container.pid() as u32, ..Default::default() }; diff --git a/crates/runc/src/container.rs b/crates/runc/src/container.rs index 93b2aed3..61ab5448 100644 --- a/crates/runc/src/container.rs +++ b/crates/runc/src/container.rs @@ -53,7 +53,6 @@ pub struct Container { #[cfg(test)] mod tests { - use std::time::SystemTime; use time::macros::datetime; use super::*; diff --git a/crates/runc/src/io.rs b/crates/runc/src/io.rs index cb56c3e2..61914afc 100644 --- a/crates/runc/src/io.rs +++ b/crates/runc/src/io.rs @@ -350,6 +350,13 @@ impl Io for FIFO { #[cfg(test)] mod tests { + #[cfg(not(feature = "async"))] + use std::{ + fs, + io::{Read, Write}, + os::unix::io::FromRawFd, + }; + use super::*; #[cfg(not(target_os = "macos"))] @@ -381,25 +388,37 @@ mod tests { stdin.write_all(&buf).unwrap(); buf[0] = 0x0; - io.stdin - .as_ref() - .map(|v| v.rd.try_clone().unwrap().read(&mut buf).unwrap()); + io.stdin.as_ref().map(|v| { + unsafe { fs::File::from_raw_fd(v.rd) } + .try_clone() + .unwrap() + .read(&mut buf) + .unwrap() + }); assert_eq!(&buf, &[0xfau8]); let mut stdout = io.stdout().unwrap(); buf[0] = 0xce; - io.stdout - .as_ref() - .map(|v| v.wr.try_clone().unwrap().write(&buf).unwrap()); + io.stdout.as_ref().map(|v| { + unsafe { fs::File::from_raw_fd(v.wr) } + .try_clone() + .unwrap() + .write(&buf) + .unwrap() + }); buf[0] = 0x0; stdout.read_exact(&mut buf).unwrap(); assert_eq!(&buf, &[0xceu8]); let mut stderr = io.stderr().unwrap(); buf[0] = 0xa5; - io.stderr - .as_ref() - .map(|v| v.wr.try_clone().unwrap().write(&buf).unwrap()); + io.stderr.as_ref().map(|v| { + unsafe { fs::File::from_raw_fd(v.wr) } + .try_clone() + .unwrap() + .write(&buf) + .unwrap() + }); buf[0] = 0x0; stderr.read_exact(&mut buf).unwrap(); assert_eq!(&buf, &[0xa5u8]); diff --git a/crates/runc/src/lib.rs b/crates/runc/src/lib.rs index 4924130f..99e27a27 100644 --- a/crates/runc/src/lib.rs +++ b/crates/runc/src/lib.rs @@ -76,9 +76,10 @@ pub struct Version { pub commit: Option, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub enum LogFormat { Json, + #[default] Text, } @@ -91,12 +92,6 @@ impl Display for LogFormat { } } -impl Default for LogFormat { - fn default() -> Self { - LogFormat::Text - } -} - #[cfg(not(feature = "async"))] pub type Command = std::process::Command; @@ -638,8 +633,6 @@ impl Runc { mod tests { use std::sync::Arc; - use time::OffsetDateTime; - use super::{ io::{InheritedStdIo, PipedStdIo}, *, @@ -1010,7 +1003,7 @@ mod tests { assert!(response.status.success()); assert!(response.output.is_empty()); - // test create cmd with pipe Io, expect nonempty cmd output + // test create cmd with pipe Io, expect empty cmd output because create uses launch_without_stdio let mut opts = CreateOpts::new(); opts.io = Some(Arc::new(PipedStdIo::new().unwrap())); let response = echo_runc @@ -1019,7 +1012,7 @@ mod tests { .expect("echo failed:"); assert_ne!(response.pid, 0); assert!(response.status.success()); - assert!(!response.output.is_empty()); + assert!(response.output.is_empty()); } } diff --git a/crates/runc/src/options.rs b/crates/runc/src/options.rs index 2df488bd..e56977c6 100644 --- a/crates/runc/src/options.rs +++ b/crates/runc/src/options.rs @@ -485,7 +485,7 @@ mod tests { fn create_opts_test() { assert_eq!( CreateOpts::new().args().expect(ARGS_FAIL_MSG), - vec![String::new(); 0] + vec![] as Vec ); assert_eq!( @@ -536,7 +536,7 @@ mod tests { fn exec_opts_test() { assert_eq!( ExecOpts::new().args().expect(ARGS_FAIL_MSG), - vec![String::new(); 0] + vec![] as Vec ); assert_eq!( @@ -576,10 +576,7 @@ mod tests { #[test] fn delete_opts_test() { - assert_eq!( - DeleteOpts::new().force(false).args(), - vec![String::new(); 0] - ); + assert_eq!(DeleteOpts::new().force(false).args(), vec![] as Vec); assert_eq!( DeleteOpts::new().force(true).args(), @@ -589,7 +586,7 @@ mod tests { #[test] fn kill_opts_test() { - assert_eq!(KillOpts::new().all(false).args(), vec![String::new(); 0]); + assert_eq!(KillOpts::new().all(false).args(), vec![] as Vec); assert_eq!(KillOpts::new().all(true).args(), vec!["--all".to_string()],); } diff --git a/crates/runc/src/utils.rs b/crates/runc/src/utils.rs index 750a116a..15596fe0 100644 --- a/crates/runc/src/utils.rs +++ b/crates/runc/src/utils.rs @@ -98,6 +98,7 @@ pub async fn write_value_to_temp_file(value: &T) -> Result>>>>, diff --git a/crates/sandbox/src/base64.rs b/crates/sandbox/src/base64.rs index 62cd81e3..85235eec 100644 --- a/crates/sandbox/src/base64.rs +++ b/crates/sandbox/src/base64.rs @@ -1,7 +1,5 @@ -use base64::engine::general_purpose::STANDARD; -use base64::Engine; -use serde::{Deserialize, Serialize}; -use serde::{Deserializer, Serializer}; +use base64::{engine::general_purpose::STANDARD, Engine}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; pub fn serialize(v: &Vec, s: S) -> Result { let base64 = STANDARD.encode(v); @@ -12,5 +10,5 @@ pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result, D::Error> let base64 = String::deserialize(d)?; STANDARD .decode(base64.as_bytes()) - .map_err(|e| serde::de::Error::custom(e)) + .map_err(serde::de::Error::custom) } diff --git a/crates/sandbox/src/config.rs b/crates/sandbox/src/config.rs index e8eb2446..0fc25853 100644 --- a/crates/sandbox/src/config.rs +++ b/crates/sandbox/src/config.rs @@ -1,7 +1,7 @@ -use serde::Deserialize; -use serde::Serialize; use std::collections::HashMap; +use serde::{Deserialize, Serialize}; + #[derive(Debug, Deserialize, Serialize, Clone)] pub struct PodSandboxConfig { pub metadata: PodSandboxMetadata, diff --git a/crates/sandbox/src/data.rs b/crates/sandbox/src/data.rs index 79d985d1..ac9de03f 100644 --- a/crates/sandbox/src/data.rs +++ b/crates/sandbox/src/data.rs @@ -1,14 +1,14 @@ -use std::collections::HashMap; -use std::time::SystemTime; +use std::{collections::HashMap, time::SystemTime}; use log::warn; use prost::Message; -use serde::Deserialize; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use tonic::Status; -use crate::spec::{JsonSpec, Mount, Process}; -use crate::PodSandboxConfig; +use crate::{ + spec::{JsonSpec, Mount, Process}, + PodSandboxConfig, +}; #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct SandboxData { @@ -68,7 +68,7 @@ impl SandboxData { netns: req.netns_path.to_string(), started_at: None, exited_at: None, - extensions: extensions, + extensions, } } diff --git a/crates/sandbox/src/lib.rs b/crates/sandbox/src/lib.rs index 5d9a7c69..bdf75bd4 100644 --- a/crates/sandbox/src/lib.rs +++ b/crates/sandbox/src/lib.rs @@ -1,23 +1,21 @@ -use std::fmt::Debug; -use std::path::Path; -use std::sync::Arc; +use std::{fmt::Debug, path::Path, sync::Arc}; use anyhow::Context; use async_trait::async_trait; +pub use cri::api::v1::PodSandboxConfig; use futures::TryFutureExt; use log::info; use serde::{Deserialize, Serialize}; -use tokio::net::UnixListener; -use tokio::sync::Mutex; +use tokio::{net::UnixListener, sync::Mutex}; use tonic::transport::Server; -pub use cri::api::v1::PodSandboxConfig; - -use crate::api::sandbox::v1::controller_server::ControllerServer; -use crate::data::{ContainerData, SandboxData}; -use crate::error::Result; -use crate::rpc::SandboxController; -use crate::signal::ExitSignal; +use crate::{ + api::sandbox::v1::controller_server::ControllerServer, + data::{ContainerData, SandboxData}, + error::Result, + rpc::SandboxController, + signal::ExitSignal, +}; pub mod args; pub mod base64; @@ -70,7 +68,7 @@ pub struct ContainerOption { impl ContainerOption { pub fn new(container: ContainerData) -> Self { - return Self { container }; + Self { container } } } @@ -88,14 +86,14 @@ pub enum SandboxStatus { Paused, } -impl ToString for SandboxStatus { - fn to_string(&self) -> String { - return match self { - Self::Created => "created".to_string(), - Self::Running(_) => "running".to_string(), - Self::Stopped(_, _) => "stopped".to_string(), - Self::Paused => "paused".to_string(), - }; +impl std::fmt::Display for SandboxStatus { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Created => write!(f, "created"), + Self::Running(_) => write!(f, "running"), + Self::Stopped(_, _) => write!(f, "stopped"), + Self::Paused => write!(f, "paused"), + } } } @@ -152,7 +150,7 @@ where .add_service(sandbox_server) .serve_with_incoming(incoming) .await - .with_context(|| format!("gRPC server"))?; + .with_context(|| "gRPC server".to_string())?; Ok(()) } diff --git a/crates/sandbox/src/rpc.rs b/crates/sandbox/src/rpc.rs index e42214bb..2e5e90dc 100644 --- a/crates/sandbox/src/rpc.rs +++ b/crates/sandbox/src/rpc.rs @@ -6,12 +6,12 @@ use time::OffsetDateTime; use tokio::fs::{create_dir_all, remove_dir_all}; use tonic::{Request, Response, Status}; -use crate::api::sandbox::v1::controller_server::Controller; -use crate::api::sandbox::v1::*; -use crate::data::{ContainerData, ProcessData, ProcessResource, SandboxData, TaskResources}; -use crate::{Container, ContainerOption, Sandbox, SandboxOption, SandboxStatus, Sandboxer}; - -use crate::utils::cleanup_mounts; +use crate::{ + api::sandbox::v1::{controller_server::Controller, *}, + data::{ContainerData, ProcessData, ProcessResource, SandboxData, TaskResources}, + utils::cleanup_mounts, + Container, ContainerOption, Sandbox, SandboxOption, SandboxStatus, Sandboxer, +}; const SANDBOX_STATUS_READY: &str = "SANDBOX_READY"; const SANDBOX_STATUS_NOTREADY: &str = "SANDBOX_NOTREADY"; @@ -57,7 +57,7 @@ where let base_dir = format!("{}/{}", self.dir, sandbox_data.id); create_dir_all(&*base_dir).await?; let opt = SandboxOption::new(base_dir.clone(), sandbox_data); - if let Err(e) = self.sandboxer.create(&*req.sandbox_id, opt).await { + if let Err(e) = self.sandboxer.create(&req.sandbox_id, opt).await { if let Err(re) = remove_dir_all(base_dir).await { warn!("roll back in sandbox create rmdir: {}", re); } @@ -105,7 +105,7 @@ where .unwrap_or_default(); return Err(tonic::Status::new( tonic::Code::Internal, - format!("sandbox status is {}", status.to_string()), + format!("sandbox status is {}", status), )); } }; @@ -170,7 +170,7 @@ where }; let mut data = { - let sandbox_mutex = self.sandboxer.sandbox(&*req.sandbox_id).await?; + let sandbox_mutex = self.sandboxer.sandbox(&req.sandbox_id).await?; let mut sandbox = sandbox_mutex.lock().await; let data = sandbox.get_data()?; let old_tasks = data.task_resources()?; @@ -190,7 +190,7 @@ where ) -> Result, Status> { let req = request.get_ref(); info!("stop sandbox {}", req.sandbox_id); - ignore_not_found!(self.sandboxer.stop(&*req.sandbox_id, true).await)?; + ignore_not_found!(self.sandboxer.stop(&req.sandbox_id, true).await)?; info!("stop sandbox {} returns successfully", req.sandbox_id); Ok(Response::new(ControllerStopResponse {})) } @@ -201,13 +201,13 @@ where ) -> Result, tonic::Status> { let req = request.get_ref(); let exit_signal = { - let sandbox_mutex = self.sandboxer.sandbox(&*req.sandbox_id).await?; + let sandbox_mutex = self.sandboxer.sandbox(&req.sandbox_id).await?; let sandbox = sandbox_mutex.lock().await; sandbox.exit_signal().await? }; exit_signal.wait().await; - let sandbox_mutex = self.sandboxer.sandbox(&*req.sandbox_id).await?; + let sandbox_mutex = self.sandboxer.sandbox(&req.sandbox_id).await?; let sandbox = sandbox_mutex.lock().await; let mut wait_resp = ControllerWaitResponse { exit_status: 0, @@ -232,7 +232,7 @@ where request: tonic::Request, ) -> Result, tonic::Status> { let req = request.get_ref(); - let sandbox_mutex = self.sandboxer.sandbox(&*req.sandbox_id).await?; + let sandbox_mutex = self.sandboxer.sandbox(&req.sandbox_id).await?; let sandbox = sandbox_mutex.lock().await; // TODO the state should match the definition in containerd let (state, pid) = match sandbox.status()? { @@ -259,7 +259,7 @@ where created_at, exited_at, extra: None, - address: address, + address, version: 2, })); } @@ -270,7 +270,7 @@ where ) -> Result, tonic::Status> { let req = request.get_ref(); info!("shutdown sandbox {}", req.sandbox_id); - ignore_not_found!(self.sandboxer.delete(&*req.sandbox_id).await)?; + ignore_not_found!(self.sandboxer.delete(&req.sandbox_id).await)?; let base_dir = format!("{}/{}", self.dir, req.sandbox_id); // Ignore clean up error cleanup_mounts(&base_dir).await.unwrap_or_default(); @@ -337,8 +337,8 @@ async fn update_process_resource( sandbox_id: &str, sb: &mut S, task_id: &str, - processes: &Vec, - old_processes: &Vec, + processes: &[ProcessResource], + old_processes: &[ProcessResource], ) -> Result<(), Status> where S: Sandbox, diff --git a/crates/sandbox/src/signal.rs b/crates/sandbox/src/signal.rs index 63f5b6d9..ace37a07 100644 --- a/crates/sandbox/src/signal.rs +++ b/crates/sandbox/src/signal.rs @@ -1,10 +1,11 @@ -use std::future::Future; -use std::pin::Pin; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::task::{Context, Poll}; +use std::{ + future::Future, + pin::Pin, + sync::atomic::{AtomicBool, Ordering}, + task::{Context, Poll}, +}; -use tokio::sync::futures::Notified; -use tokio::sync::Notify; +use tokio::sync::{futures::Notified, Notify}; /// Helper structure that wraps atomic bool to signal shim server when to shutdown the TTRPC server. /// @@ -43,10 +44,10 @@ impl ExitSignal { pub fn exited(&self) -> Exited { let notified = self.notifier.notified(); - return Exited { + Exited { notified, - sig: &self, - }; + sig: self, + } } } @@ -66,6 +67,6 @@ impl Future for Exited<'_> { if this.sig.exited.load(Ordering::SeqCst) { return Poll::Ready(()); } - return this.notified.poll(cx); + this.notified.poll(cx) } } diff --git a/crates/sandbox/src/spec.rs b/crates/sandbox/src/spec.rs index c9b50685..56c6a616 100644 --- a/crates/sandbox/src/spec.rs +++ b/crates/sandbox/src/spec.rs @@ -1,11 +1,10 @@ use std::collections::HashMap; use anyhow::anyhow; -use serde::Deserialize; -use serde::Serialize; +use prost_types::Any; +use serde::{Deserialize, Serialize}; use crate::error::Result; -use prost_types::Any; #[derive(Debug, Deserialize, Serialize, Clone, Default)] pub struct JsonSpec { @@ -456,6 +455,12 @@ pub struct Hook { pub timeout: i64, } +impl Default for Process { + fn default() -> Self { + Self::new() + } +} + impl Process { pub fn new() -> Process { Process { @@ -482,17 +487,17 @@ impl Process { } } -const CRI_CONTAINERD_CONTAINER_TYPE_KEY: &'static str = "io.kubernetes.cri.container-type"; -const CRIO_CONTAINER_TYPE_KEY: &'static str = "io.kubernetes.cri-o.ContainerType"; -const DOCKERSHIM_CONTAINER_TYPE_KEY: &'static str = "io.kubernetes.docker.type"; +const CRI_CONTAINERD_CONTAINER_TYPE_KEY: &str = "io.kubernetes.cri.container-type"; +const CRIO_CONTAINER_TYPE_KEY: &str = "io.kubernetes.cri-o.ContainerType"; +const DOCKERSHIM_CONTAINER_TYPE_KEY: &str = "io.kubernetes.docker.type"; -const CONTAINER_TYPE_SANDBOX: &'static str = "sandbox"; -const CONTAINER_TYPE_PODSANDBOX: &'static str = "podsandbox"; -const CONTAINER_TYPE_CONTAINER: &'static str = "container"; +const CONTAINER_TYPE_SANDBOX: &str = "sandbox"; +const CONTAINER_TYPE_PODSANDBOX: &str = "podsandbox"; +const CONTAINER_TYPE_CONTAINER: &str = "container"; -const CRI_CONTAINERD_SANDBOX_ID_KEY: &'static str = "io.kubernetes.cri.sandbox-id"; -const CRIO_SANDBOX_ID_KEY: &'static str = "io.kubernetes.cri-o.SandboxID"; -const DOCKERSHIM_SANDBOX_ID_KEY: &'static str = "io.kubernetes.sandbox.id"; +const CRI_CONTAINERD_SANDBOX_ID_KEY: &str = "io.kubernetes.cri.sandbox-id"; +const CRIO_SANDBOX_ID_KEY: &str = "io.kubernetes.cri-o.SandboxID"; +const DOCKERSHIM_SANDBOX_ID_KEY: &str = "io.kubernetes.sandbox.id"; #[derive(Debug)] pub enum ContainerType { @@ -511,7 +516,7 @@ impl ContainerType { _ => {} } } - return Self::Sandbox; + Self::Sandbox } } @@ -551,23 +556,23 @@ pub fn to_any(spec: &JsonSpec) -> Result { impl From<&crate::types::Mount> for Mount { fn from(m: &crate::types::Mount) -> Self { - return Self { + Self { destination: "".to_string(), r#type: m.r#type.to_string(), source: m.source.to_string(), options: m.options.clone(), - }; + } } } impl From<&Mount> for crate::types::Mount { fn from(m: &Mount) -> Self { - return Self { + Self { r#type: m.r#type.to_string(), source: m.source.to_string(), target: m.destination.to_string(), options: m.options.clone(), - }; + } } } @@ -842,7 +847,7 @@ mod tests { ] } }"#; - let spec = serde_json::from_str::(&spec_str).unwrap(); + let spec = serde_json::from_str::(spec_str).unwrap(); assert!(spec.vm.is_none()); assert_eq!( spec.linux.unwrap().cgroups_path, diff --git a/crates/sandbox/src/utils.rs b/crates/sandbox/src/utils.rs index 88304a7b..fc4d4e90 100644 --- a/crates/sandbox/src/utils.rs +++ b/crates/sandbox/src/utils.rs @@ -1,13 +1,19 @@ +#[cfg(target_os = "linux")] use anyhow::anyhow; +#[cfg(target_os = "linux")] use log::{debug, error}; +#[cfg(target_os = "linux")] use nix::errno::Errno; +#[cfg(target_os = "linux")] use nix::NixPath; +#[cfg(target_os = "linux")] use crate::error::Error; use crate::Result; +#[cfg(target_os = "linux")] pub async fn cleanup_mounts(parent_dir: &str) -> Result<()> { - let parent_dir = if parent_dir.len() == 0 { + let parent_dir = if parent_dir.is_empty() { "." } else { parent_dir @@ -17,8 +23,11 @@ pub async fn cleanup_mounts(parent_dir: &str) -> Result<()> { .map_err(Error::IO)?; for line in mounts.lines() { let fields = line.split_whitespace().collect::>(); + if fields.len() < 2 { + continue; + } let path = fields[1]; - if path.starts_with(&parent_dir) { + if path.starts_with(parent_dir) { unmount(path, libc::MNT_DETACH | libc::UMOUNT_NOFOLLOW).unwrap_or_else(|e| { error!("failed to remove {}, err: {}", path, e); }); @@ -27,20 +36,31 @@ pub async fn cleanup_mounts(parent_dir: &str) -> Result<()> { Ok(()) } +#[cfg(target_os = "linux")] pub fn unmount(target: &str, flags: i32) -> Result<()> { let res = target .with_nix_path(|cstr| unsafe { libc::umount2(cstr.as_ptr(), flags) }) .map_err(|e| anyhow!("failed to umount {}, {}", target, e))?; let err = Errno::result(res).map(drop); match err { - Ok(_) => return Ok(()), + Ok(_) => Ok(()), Err(e) => { if e == Errno::ENOENT { debug!("the umount path {} not exist", target); return Ok(()); } - return Err(anyhow!("failed to umount {}, {}", target, e).into()); + Err(anyhow!("failed to umount {}, {}", target, e).into()) } } } + +#[cfg(not(target_os = "linux"))] +pub async fn cleanup_mounts(_parent_dir: &str) -> Result<()> { + Ok(()) +} + +#[cfg(not(target_os = "linux"))] +pub fn unmount(_target: &str, _flags: i32) -> Result<()> { + Ok(()) +} diff --git a/crates/shim/examples/skeleton_async.rs b/crates/shim/examples/skeleton_async.rs index af492715..b4c06479 100644 --- a/crates/shim/examples/skeleton_async.rs +++ b/crates/shim/examples/skeleton_async.rs @@ -35,6 +35,8 @@ struct Service { #[async_trait] impl Shim for Service { type T = Service; + #[cfg(feature = "sandbox")] + type S = containerd_shim::asynchronous::NoopSandboxService; async fn new(_runtime_id: &str, _id: &str, _namespace: &str, _config: &mut Config) -> Self { Service { @@ -42,7 +44,12 @@ impl Shim for Service { } } - async fn start_shim(&mut self, opts: StartOpts) -> Result { + #[cfg(feature = "sandbox")] + async fn create_sandbox_service(&self) -> Self::S { + containerd_shim::asynchronous::NoopSandboxService + } + + async fn start_shim(&mut self, opts: StartOpts) -> containerd_shim::Result { let grouping = opts.id.clone(); let address = spawn(opts, &grouping, Vec::new()).await?; Ok(address) diff --git a/crates/shim/src/args.rs b/crates/shim/src/args.rs index 9147e37e..2d8b6076 100644 --- a/crates/shim/src/args.rs +++ b/crates/shim/src/args.rs @@ -57,7 +57,7 @@ pub fn parse>(args: &[S]) -> Result { }) .map_err(|e| Error::InvalidArgument(e.to_string()))?; - if let Some(action) = args.get(0) { + if let Some(action) = args.first() { flags.action = action.into(); } diff --git a/crates/shim/src/asynchronous/cgroup_memory.rs b/crates/shim/src/asynchronous/cgroup_memory.rs index 594da24d..37a767c9 100644 --- a/crates/shim/src/asynchronous/cgroup_memory.rs +++ b/crates/shim/src/asynchronous/cgroup_memory.rs @@ -16,28 +16,26 @@ #![cfg(target_os = "linux")] -use cgroups_rs::hierarchies::is_cgroup2_unified_mode; -use log::warn; use std::{ os::unix::io::{AsRawFd, FromRawFd}, path::Path, }; -use crate::{ - error::{Error, Result}, - io_error, other_error, -}; - -use crate::event::Event; -use containerd_shim_protos::events::task::TaskOOM; -use containerd_shim_protos::protobuf::MessageDyn; +use cgroups_rs::hierarchies::is_cgroup2_unified_mode; +use containerd_shim_protos::{events::task::TaskOOM, protobuf::MessageDyn}; +use log::warn; use nix::sys::eventfd::{EfdFlags, EventFd}; -use tokio::sync::mpsc::Sender; use tokio::{ fs::{self, read_to_string, File}, io::AsyncReadExt, spawn, - sync::mpsc::{self, Receiver}, + sync::mpsc::{self, Receiver, Sender}, +}; + +use crate::{ + error::{Error, Result}, + event::Event, + io_error, other_error, }; pub type EventSender = Sender<(String, Box)>; @@ -155,7 +153,7 @@ pub async fn register_memory_event( let mut eventfd_file = unsafe { File::from_raw_fd(eventfd.as_raw_fd()) }; loop { match eventfd_file.read(&mut buf).await { - Ok(bytes_read) if bytes_read == 0 => return, + Ok(0) => return, Err(_) => return, _ => (), } @@ -173,9 +171,6 @@ pub async fn register_memory_event( mod tests { use std::path::Path; - use crate::asynchronous::cgroup_memory::{ - get_existing_cgroup_mem_path, get_path_from_cgorup, register_memory_event, - }; use cgroups_rs::{ hierarchies::{self, is_cgroup2_unified_mode}, memory::MemController, @@ -183,6 +178,10 @@ mod tests { }; use tokio::{fs::remove_file, io::AsyncWriteExt, process::Command}; + use crate::asynchronous::cgroup_memory::{ + get_existing_cgroup_mem_path, get_path_from_cgorup, register_memory_event, + }; + #[tokio::test] async fn test_cgroupv1_oom_monitor() { if !is_cgroup2_unified_mode() { diff --git a/crates/shim/src/asynchronous/mod.rs b/crates/shim/src/asynchronous/mod.rs index d6225a30..d13cce72 100644 --- a/crates/shim/src/asynchronous/mod.rs +++ b/crates/shim/src/asynchronous/mod.rs @@ -33,7 +33,7 @@ use std::{ use async_trait::async_trait; use command_fds::{CommandFdExt, FdMapping}; #[cfg(feature = "sandbox")] -use containerd_shim_protos::sandbox::sandbox_ttrpc::{create_sandbox, Sandbox}; +use containerd_shim_protos::sandbox::sandbox_ttrpc::create_sandbox; use containerd_shim_protos::{ api::DeleteResponse, protobuf::Message, @@ -75,6 +75,93 @@ pub mod publisher; pub mod task; pub mod util; +#[cfg(feature = "sandbox")] +#[derive(Clone, Default)] +pub struct NoopSandboxService; + +#[cfg(feature = "sandbox")] +#[async_trait] +impl containerd_shim_protos::sandbox::sandbox_ttrpc::Sandbox for NoopSandboxService { + async fn create_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::r#async::TtrpcContext, + _req: containerd_shim_protos::sandbox::sandbox::CreateSandboxRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::CreateSandboxResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::CreateSandboxResponse::default()) + } + + async fn start_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::r#async::TtrpcContext, + _req: containerd_shim_protos::sandbox::sandbox::StartSandboxRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::StartSandboxResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::StartSandboxResponse::default()) + } + + async fn platform( + &self, + _ctx: &containerd_shim_protos::ttrpc::r#async::TtrpcContext, + _req: containerd_shim_protos::sandbox::sandbox::PlatformRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::PlatformResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::PlatformResponse::default()) + } + + async fn stop_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::r#async::TtrpcContext, + _req: containerd_shim_protos::sandbox::sandbox::StopSandboxRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::StopSandboxResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::StopSandboxResponse::default()) + } + + async fn wait_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::r#async::TtrpcContext, + _req: containerd_shim_protos::sandbox::sandbox::WaitSandboxRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::WaitSandboxResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::WaitSandboxResponse::default()) + } + + async fn sandbox_status( + &self, + _ctx: &containerd_shim_protos::ttrpc::r#async::TtrpcContext, + _req: containerd_shim_protos::sandbox::sandbox::SandboxStatusRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::SandboxStatusResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::SandboxStatusResponse::default()) + } + + async fn ping_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::r#async::TtrpcContext, + _req: containerd_shim_protos::sandbox::sandbox::PingRequest, + ) -> containerd_shim_protos::ttrpc::Result + { + Ok(containerd_shim_protos::sandbox::sandbox::PingResponse::default()) + } + + async fn shutdown_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::r#async::TtrpcContext, + _req: containerd_shim_protos::sandbox::sandbox::ShutdownSandboxRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::ShutdownSandboxResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::ShutdownSandboxResponse::default()) + } +} + /// Asynchronous Main shim interface that must be implemented by all async shims. /// /// Start and delete routines will be called to handle containerd's shim lifecycle requests. @@ -83,6 +170,10 @@ pub trait Shim { /// Type to provide task service for the shim. type T: Task + Send + Sync; + /// Type to provide sandbox service for the shim. + #[cfg(feature = "sandbox")] + type S: containerd_shim_protos::sandbox::sandbox_ttrpc::Sandbox + Send + Sync; + /// Create a new instance of async Shim. /// /// # Arguments @@ -92,6 +183,10 @@ pub trait Shim { /// - `config`: for the shim to pass back configuration information async fn new(runtime_id: &str, id: &str, namespace: &str, config: &mut Config) -> Self; + /// Create the sandbox service object. + #[cfg(feature = "sandbox")] + async fn create_sandbox_service(&self) -> Self::S; + /// Start shim will be called by containerd when launching new shim instance. /// /// It expected to return TTRPC address containerd daemon can use to communicate with @@ -109,12 +204,6 @@ pub trait Shim { /// Create the task service object asynchronously. async fn create_task_service(&self, publisher: RemotePublisher) -> Self::T; - - #[cfg(feature = "sandbox")] - type S: Sandbox + Send + Sync; - - #[cfg(feature = "sandbox")] - async fn create_sandbox_service(&self) -> Self::S; } /// Async Shim entry point that must be invoked from tokio `main`. @@ -260,10 +349,10 @@ impl ExitSignal { pub fn exited(&self) -> Exited { let notified = self.notifier.notified(); - return Exited { + Exited { notified, - sig: &self, - }; + sig: self, + } } } @@ -283,7 +372,7 @@ impl Future for Exited<'_> { if this.sig.exited.load(Ordering::SeqCst) { return Poll::Ready(()); } - return this.notified.poll(cx); + this.notified.poll(cx) } } diff --git a/crates/shim/src/asynchronous/monitor.rs b/crates/shim/src/asynchronous/monitor.rs index 3ee30e1a..d06375dd 100644 --- a/crates/shim/src/asynchronous/monitor.rs +++ b/crates/shim/src/asynchronous/monitor.rs @@ -109,10 +109,7 @@ impl Monitor { }; self.subscribers.insert(id, subscriber); - self.topic_subs - .entry(topic) - .or_insert_with(Vec::new) - .push(id); + self.topic_subs.entry(topic).or_default().push(id); Ok(Subscription { id, rx }) } diff --git a/crates/shim/src/asynchronous/processes.rs b/crates/shim/src/asynchronous/processes.rs index 67f9c569..b5ffd727 100644 --- a/crates/shim/src/asynchronous/processes.rs +++ b/crates/shim/src/asynchronous/processes.rs @@ -24,9 +24,13 @@ use containerd_shim_protos::{ }; use oci_spec::runtime::LinuxResources; use time::OffsetDateTime; -use tokio::fs::File; -use tokio::sync::oneshot::{channel, Receiver, Sender}; -use tokio::sync::Mutex; +use tokio::{ + fs::File, + sync::{ + oneshot::{channel, Receiver, Sender}, + Mutex, + }, +}; use crate::{io::Stdio, ioctl_set_winsz, util::asyncify, Console}; diff --git a/crates/shim/src/asynchronous/task.rs b/crates/shim/src/asynchronous/task.rs index 57d69b2f..ccdd6227 100644 --- a/crates/shim/src/asynchronous/task.rs +++ b/crates/shim/src/asynchronous/task.rs @@ -32,7 +32,6 @@ use log::{debug, error, info, warn}; use oci_spec::runtime::LinuxResources; use tokio::sync::{mpsc::Sender, MappedMutexGuard, Mutex, MutexGuard}; -use crate::asynchronous::cgroup_memory::monitor_oom; use crate::{ api::{ CreateTaskRequest, CreateTaskResponse, DeleteRequest, Empty, ExecProcessRequest, @@ -40,6 +39,7 @@ use crate::{ StateResponse, Status, WaitRequest, WaitResponse, }, asynchronous::{ + cgroup_memory::monitor_oom, container::{Container, ContainerFactory}, ExitSignal, }, @@ -387,7 +387,7 @@ where let container = self.get_container(req.id()).await?; Ok(ConnectResponse { - shim_pid: std::process::id() as u32, + shim_pid: std::process::id(), task_pid: container.pid().await as u32, ..Default::default() }) diff --git a/crates/shim/src/cgroup.rs b/crates/shim/src/cgroup.rs index cadc9899..e7ce92bd 100644 --- a/crates/shim/src/cgroup.rs +++ b/crates/shim/src/cgroup.rs @@ -248,7 +248,7 @@ pub fn collect_metrics(pid: u32) -> Result { Ok(metrics) } -fn set_cpu_usage_and_throttle(stat: &String, cpu_stat: &mut CPUStat) { +fn set_cpu_usage_and_throttle(stat: &str, cpu_stat: &mut CPUStat) { for line in stat.lines() { let parts = line.split_whitespace().collect::>(); if parts.len() == 2 { diff --git a/crates/shim/src/synchronous/mod.rs b/crates/shim/src/synchronous/mod.rs index 7f839fac..a5dfd732 100644 --- a/crates/shim/src/synchronous/mod.rs +++ b/crates/shim/src/synchronous/mod.rs @@ -73,6 +73,92 @@ pub mod monitor; pub mod publisher; pub mod util; +#[cfg(feature = "sandbox")] +#[derive(Clone, Default)] +pub struct NoopSandboxService; + +#[cfg(feature = "sandbox")] +impl containerd_shim_protos::sandbox::sandbox_ttrpc::Sandbox for NoopSandboxService { + fn create_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::Context, + _req: containerd_shim_protos::sandbox::sandbox::CreateSandboxRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::CreateSandboxResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::CreateSandboxResponse::default()) + } + + fn start_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::Context, + _req: containerd_shim_protos::sandbox::sandbox::StartSandboxRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::StartSandboxResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::StartSandboxResponse::default()) + } + + fn platform( + &self, + _ctx: &containerd_shim_protos::ttrpc::Context, + _req: containerd_shim_protos::sandbox::sandbox::PlatformRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::PlatformResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::PlatformResponse::default()) + } + + fn stop_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::Context, + _req: containerd_shim_protos::sandbox::sandbox::StopSandboxRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::StopSandboxResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::StopSandboxResponse::default()) + } + + fn wait_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::Context, + _req: containerd_shim_protos::sandbox::sandbox::WaitSandboxRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::WaitSandboxResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::WaitSandboxResponse::default()) + } + + fn sandbox_status( + &self, + _ctx: &containerd_shim_protos::ttrpc::Context, + _req: containerd_shim_protos::sandbox::sandbox::SandboxStatusRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::SandboxStatusResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::SandboxStatusResponse::default()) + } + + fn ping_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::Context, + _req: containerd_shim_protos::sandbox::sandbox::PingRequest, + ) -> containerd_shim_protos::ttrpc::Result + { + Ok(containerd_shim_protos::sandbox::sandbox::PingResponse::default()) + } + + fn shutdown_sandbox( + &self, + _ctx: &containerd_shim_protos::ttrpc::Context, + _req: containerd_shim_protos::sandbox::sandbox::ShutdownSandboxRequest, + ) -> containerd_shim_protos::ttrpc::Result< + containerd_shim_protos::sandbox::sandbox::ShutdownSandboxResponse, + > { + Ok(containerd_shim_protos::sandbox::sandbox::ShutdownSandboxResponse::default()) + } +} + pub mod console; /// Helper structure that wraps atomic bool to signal shim server when to shutdown the TTRPC server. @@ -109,6 +195,10 @@ pub trait Shim { /// Type to provide task service for the shim. type T: Task + Send + Sync; + /// Type to provide sandbox service for the shim. + #[cfg(feature = "sandbox")] + type S: containerd_shim_protos::sandbox::sandbox_ttrpc::Sandbox + Send + Sync; + /// Create a new instance of Shim. /// /// # Arguments @@ -118,6 +208,10 @@ pub trait Shim { /// - `config`: for the shim to pass back configuration information fn new(runtime_id: &str, id: &str, namespace: &str, config: &mut Config) -> Self; + /// Create the sandbox service object. + #[cfg(feature = "sandbox")] + fn create_sandbox_service(&self) -> Self::S; + /// Start shim will be called by containerd when launching new shim instance. /// /// It expected to return TTRPC address containerd daemon can use to communicate with diff --git a/crates/shim/src/synchronous/monitor.rs b/crates/shim/src/synchronous/monitor.rs index 9c7c5cfa..9a401a00 100644 --- a/crates/shim/src/synchronous/monitor.rs +++ b/crates/shim/src/synchronous/monitor.rs @@ -95,10 +95,7 @@ impl Monitor { topic: topic.clone(), }; self.subscribers.insert(id, subscriber); - self.topic_subs - .entry(topic) - .or_insert_with(Vec::new) - .push(id); + self.topic_subs.entry(topic).or_default().push(id); Ok(Subscription { id, rx }) } diff --git a/crates/snapshots/examples/snapshotter.rs b/crates/snapshots/examples/snapshotter.rs index 7fa768d8..77a197ed 100644 --- a/crates/snapshots/examples/snapshotter.rs +++ b/crates/snapshots/examples/snapshotter.rs @@ -107,7 +107,7 @@ async fn main() { .ok_or("First argument must be socket path") .unwrap(); - let example = Example::default(); + let example = Example; let incoming = { let uds = UnixListener::bind(socket_path).expect("Failed to bind listener"); @@ -153,9 +153,11 @@ mod unix { } } - #[derive(Clone, Debug)] + #[derive(Debug, Clone)] pub struct UdsConnectInfo { + #[allow(dead_code)] pub peer_addr: Option>, + #[allow(dead_code)] pub peer_cred: Option, } diff --git a/crates/snapshots/src/lib.rs b/crates/snapshots/src/lib.rs index 381d1512..a79fe097 100644 --- a/crates/snapshots/src/lib.rs +++ b/crates/snapshots/src/lib.rs @@ -78,20 +78,15 @@ pub mod api { } /// Snapshot kinds. -#[derive(Debug)] +#[derive(Debug, Default)] pub enum Kind { + #[default] Unknown, View, Active, Committed, } -impl Default for Kind { - fn default() -> Self { - Kind::Unknown - } -} - /// Information about a particular snapshot. #[derive(Debug)] pub struct Info { diff --git a/deny.toml b/deny.toml index 95517879..fc77b3ad 100644 --- a/deny.toml +++ b/deny.toml @@ -1,71 +1,37 @@ -# This template contains all of the possible sections and their default values - -# Note that all fields that take a lint level have these possible values: -# * deny - An error will be produced and the check will fail -# * warn - A warning will be produced, but the check will not fail -# * allow - No warning or error will be produced, though in some cases a note -# will be - -# The values provided in this template are the default values that will be used -# when any section or field is not specified in your own configuration - +# This section is considered when running `cargo deny check` +[graph] # If 1 or more target triples (and optionally, target_features) are specified, # only the specified targets will be checked when running `cargo deny check`. -# This means, if a particular package is only ever used as a target specific -# dependency, such as, for example, the `nix` crate only being used via the -# `target_family = "unix"` configuration, that only having windows targets in -# this list would mean the nix crate, as well as any of its exclusive -# dependencies not shared by any other crates, would be ignored, as the target -# list here is effectively saying which targets you are building for. targets = [ - # The triple can be any string, but only the target triples built in to - # rustc (as of 1.40) can be checked against actual config expressions - #{ triple = "x86_64-unknown-linux-musl" }, - # You can also specify which target_features you promise are enabled for a - # particular target. target_features are currently not validated against - # the actual valid features supported by the target architecture. - #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, ] # This section is considered when running `cargo deny check advisories` # More documentation for the advisories section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html [advisories] +version = 2 # The path where the advisory database is cloned/fetched into db-path = "~/.cargo/advisory-db" # The url(s) of the advisory databases to use db-urls = ["https://github.com/rustsec/advisory-db"] -# The lint level for security vulnerabilities -vulnerability = "deny" -# The lint level for unmaintained crates -unmaintained = "warn" -# The lint level for crates that have been yanked from their source registry -yanked = "warn" -# The lint level for crates with security notices. Note that as of -# 2019-12-17 there are no security notice advisories in -# https://github.com/rustsec/advisory-db -notice = "warn" +# How to handle unmaintained advisories +unmaintained = "all" +# How to handle yanked crates +yanked = "deny" +# How to handle unsound advisories +unsound = "all" # A list of advisory IDs to ignore. Note that ignored advisories will still # output a note when they are encountered. ignore = [ - #"RUSTSEC-0000-0000", + "RUSTSEC-2024-0437", # protobuf 2.28.0 uncontrolled recursion + "RUSTSEC-2026-0009", # time 0.3.36 Denial of Service via Stack Exhaustion ] -# Threshold for security vulnerabilities, any vulnerability with a CVSS score -# lower than the range specified will be ignored. Note that ignored advisories -# will still output a note when they are encountered. -# * None - CVSS Score 0.0 -# * Low - CVSS Score 0.1 - 3.9 -# * Medium - CVSS Score 4.0 - 6.9 -# * High - CVSS Score 7.0 - 8.9 -# * Critical - CVSS Score 9.0 - 10.0 -#severity-threshold = # This section is considered when running `cargo deny check licenses` # More documentation for the licenses section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html [licenses] -# The lint level for crates which do not have a detectable license -unlicensed = "deny" +version = 2 # List of explictly allowed licenses # See https://spdx.org/licenses/ for list of possible licenses # [possible values: any SPDX 3.11 short identifier (+ optional exception)]. @@ -73,27 +39,8 @@ allow = [ "MIT", "Apache-2.0", "BSD-3-Clause", + "Unicode-3.0", ] -# List of explictly disallowed licenses -# See https://spdx.org/licenses/ for list of possible licenses -# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. -deny = [ - #"Nokia", -] -# Lint level for licenses considered copyleft -copyleft = "warn" -# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses -# * both - The license will be approved if it is both OSI-approved *AND* FSF -# * either - The license will be approved if it is either OSI-approved *OR* FSF -# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF -# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved -# * neither - This predicate is ignored and the default lint level is used -allow-osi-fsf-free = "neither" -# Lint level used when no other predicates are matched -# 1. License isn't in the allow or deny lists -# 2. License isn't copyleft -# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" -default = "deny" # The confidence threshold for detecting a license from license text. # The higher the value, the more closely the license text must be to the # canonical license text of a valid SPDX license file. @@ -107,26 +54,6 @@ exceptions = [ { allow = ["Unicode-DFS-2016"], name = "unicode-ident", version = "*" }, ] -# Some crates don't have (easily) machine readable licensing information, -# adding a clarification entry for it allows you to manually specify the -# licensing information -#[[licenses.clarify]] -# The name of the crate the clarification applies to -#name = "ring" -# The optional version constraint for the crate -#version = "*" -# The SPDX expression for the license requirements of the crate -#expression = "MIT AND ISC AND OpenSSL" -# One or more files in the crate's source used as the "source of truth" for -# the license expression. If the contents match, the clarification will be used -# when running the license check, otherwise the clarification will be ignored -# and the crate will be checked normally, which may produce warnings or errors -# depending on the rest of your configuration -#license-files = [ - # Each entry is a crate relative path, and the (opaque) hash of its contents - #{ path = "LICENSE", hash = 0xbd0eed23 } -#] - [licenses.private] # If true, ignores workspace crates that aren't published, or are only # published to private registries @@ -142,10 +69,6 @@ registries = [ # More documentation about the 'bans' section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html [bans] -# Lint level for when multiple versions of the same crate are detected -multiple-versions = "warn" -# Lint level for when a crate version requirement is `*` -wildcards = "allow" # The graph highlighting used when creating dotgraphs for crates # with multiple versions # * lowest-version - The path to the lowest versioned duplicate is highlighted @@ -178,18 +101,26 @@ skip-tree = [ #{ name = "ansi_term", version = "=0.11.0", depth = 20 }, ] +# Lint level for when multiple versions of the same crate are detected +multiple-versions = "warn" +# Lint level for when a crate version requirement is `*` +wildcards = "allow" + # This section is considered when running `cargo deny check sources`. # More documentation about the 'sources' section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html [sources] +# List of URLs for allowed crate registries. Defaults to the crates.io index +# if not specified. If it is specified but empty, no registries are allowed. +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +# List of URLs for allowed Git repositories +allow-git = [ + "https://github.com/kuasar-io/ttrpc-rust.git" +] + # Lint level for what to happen when a crate from a crate registry that is not # in the allow list is encountered unknown-registry = "warn" # Lint level for what to happen when a crate from a git repository that is not # in the allow list is encountered unknown-git = "warn" -# List of URLs for allowed crate registries. Defaults to the crates.io index -# if not specified. If it is specified but empty, no registries are allowed. -allow-registry = ["https://github.com/rust-lang/crates.io-index"] -# List of URLs for allowed Git repositories -allow-git = [] diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 509f3ab0..5e53890a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.81" -components = ["rustfmt", "clippy"] +channel = "1.85" +components = ["rustfmt", "clippy", "llvm-tools"]