libcontainer/container/
container_kill.rs1use libcgroups::common::{CgroupManager, get_cgroup_setup};
2use nix::sys::signal::{self};
3
4use super::{Container, ContainerStatus};
5use crate::error::LibcontainerError;
6use crate::signal::Signal;
7
8impl Container {
9 pub fn kill<S: Into<Signal>>(&mut self, signal: S, all: bool) -> Result<(), LibcontainerError> {
31 self.refresh_status()?;
32 match self.can_kill() {
33 true => {
34 self.do_kill(signal, all)?;
35 }
36 false if all && self.status() == ContainerStatus::Stopped => {
37 self.do_kill(signal, all)?;
38 }
39 false => {
40 tracing::error!(id = ?self.id(), status = ?self.status(), "cannot kill container due to incorrect state");
41 return Err(LibcontainerError::IncorrectStatus(self.status()));
42 }
43 }
44 self.set_status(ContainerStatus::Stopped).save()?;
45 Ok(())
46 }
47
48 pub(crate) fn do_kill<S: Into<Signal>>(
49 &self,
50 signal: S,
51 all: bool,
52 ) -> Result<(), LibcontainerError> {
53 if all {
54 self.kill_all_processes(signal)
55 } else {
56 self.kill_one_process(signal)
57 }
58 }
59
60 fn kill_one_process<S: Into<Signal>>(&self, signal: S) -> Result<(), LibcontainerError> {
61 let signal = signal.into().into_raw();
62 let pid = self.pid().ok_or(LibcontainerError::Other(
63 "container process pid not found in state".into(),
64 ))?;
65
66 tracing::debug!("kill signal {} to {}", signal, pid);
67
68 match signal::kill(pid, signal) {
69 Ok(_) => {}
70 Err(nix::errno::Errno::ESRCH) => {
71 }
73 Err(err) => {
74 tracing::error!(id = ?self.id(), err = ?err, ?pid, ?signal, "failed to kill process");
75 return Err(LibcontainerError::OtherSyscall(err));
76 }
77 }
78
79 if self.status() == ContainerStatus::Paused && signal == signal::Signal::SIGKILL {
82 match get_cgroup_setup()? {
83 libcgroups::common::CgroupSetup::Legacy
84 | libcgroups::common::CgroupSetup::Hybrid => {
85 let cmanager = libcgroups::common::create_cgroup_manager(
86 libcgroups::common::CgroupConfig {
87 cgroup_path: self.spec()?.cgroup_path,
88 systemd_cgroup: self.systemd(),
89 container_name: self.id().to_string(),
90 },
91 )?;
92 cmanager.freeze(libcgroups::common::FreezerState::Thawed)?;
93 }
94 libcgroups::common::CgroupSetup::Unified => {}
95 }
96 }
97 Ok(())
98 }
99
100 fn kill_all_processes<S: Into<Signal>>(&self, signal: S) -> Result<(), LibcontainerError> {
101 let signal = signal.into().into_raw();
102 let cmanager =
103 libcgroups::common::create_cgroup_manager(libcgroups::common::CgroupConfig {
104 cgroup_path: self.spec()?.cgroup_path,
105 systemd_cgroup: self.systemd(),
106 container_name: self.id().to_string(),
107 })?;
108
109 if let Err(e) = cmanager.freeze(libcgroups::common::FreezerState::Frozen) {
110 tracing::warn!(
111 err = ?e,
112 id = ?self.id(),
113 "failed to freeze container",
114 );
115 }
116
117 let pids = cmanager.get_all_pids()?;
118 pids.iter()
119 .try_for_each(|&pid| {
120 tracing::debug!("kill signal {} to {}", signal, pid);
121 let res = signal::kill(pid, signal);
122 match res {
123 Err(nix::errno::Errno::ESRCH) => {
124 Ok(())
126 }
127 _ => res,
128 }
129 })
130 .map_err(LibcontainerError::OtherSyscall)?;
131 if let Err(err) = cmanager.freeze(libcgroups::common::FreezerState::Thawed) {
132 tracing::warn!(
133 err = ?err,
134 id = ?self.id(),
135 "failed to thaw container",
136 );
137 }
138
139 Ok(())
140 }
141}