Skip to content

Commit aaa7868

Browse files
bors[bot]MikailBag
andauthored
Merge #56
56: Simplify sandbox r=MikailBag a=MikailBag Co-authored-by: Mikail Bagishov <bagishov.mikail@yandex.ru>
2 parents 3330cb7 + ac4b5d9 commit aaa7868

File tree

7 files changed

+55
-71
lines changed

7 files changed

+55
-71
lines changed

minion-ffi/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::{
55
ffi::{CStr, OsStr, OsString},
66
mem::{self},
77
os::raw::c_char,
8+
sync::Arc,
89
};
910

1011
#[repr(i32)]
@@ -106,7 +107,7 @@ pub struct SandboxOptions {
106107
}
107108

108109
#[derive(Clone)]
109-
pub struct Sandbox(Box<dyn minion::erased::Sandbox>);
110+
pub struct Sandbox(Arc<dyn minion::erased::Sandbox>);
110111

111112
/// # Safety
112113
/// `out` must be valid

src/command.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ use crate::{erased, InputSpecification, OutputSpecification, StdioSpecification}
22
use std::{
33
ffi::{OsStr, OsString},
44
path::{Path, PathBuf},
5+
sync::Arc,
56
};
67

78
/// Child process builder
89
#[derive(Default, Debug)]
910
pub struct Command {
10-
sandbox: Option<Box<dyn erased::Sandbox>>,
11+
sandbox: Option<Arc<dyn erased::Sandbox>>,
1112
exe: Option<PathBuf>,
1213
argv: Vec<OsString>,
1314
env: Vec<OsString>,
@@ -56,7 +57,7 @@ impl Command {
5657
backend.spawn(options)
5758
}
5859

59-
pub fn sandbox(&mut self, sandbox: Box<dyn erased::Sandbox>) -> &mut Self {
60+
pub fn sandbox(&mut self, sandbox: Arc<dyn erased::Sandbox>) -> &mut Self {
6061
self.sandbox.replace(sandbox);
6162
self
6263
}

src/erased.rs

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//!
44
//! Please note that this API is not type-safe. For example, if you pass
55
//! `Sandbox` instance to another backend, it will panic.
6+
use std::{any::Any, sync::Arc};
67

78
use futures_util::{FutureExt, TryFutureExt};
89

@@ -13,16 +14,7 @@ pub trait Sandbox: std::fmt::Debug + Send + Sync + 'static {
1314
fn check_real_tle(&self) -> anyhow::Result<bool>;
1415
fn kill(&self) -> anyhow::Result<()>;
1516
fn resource_usage(&self) -> anyhow::Result<crate::ResourceUsageData>;
16-
#[doc(hidden)]
17-
fn clone_to_box(&self) -> Box<dyn Sandbox>;
18-
#[doc(hidden)]
19-
fn clone_into_box_any(&self) -> Box<dyn std::any::Any>;
20-
}
21-
22-
impl Clone for Box<dyn Sandbox> {
23-
fn clone(&self) -> Self {
24-
self.clone_to_box()
25-
}
17+
fn into_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync + 'static>;
2618
}
2719

2820
impl<S: crate::Sandbox> Sandbox for S {
@@ -41,12 +33,8 @@ impl<S: crate::Sandbox> Sandbox for S {
4133
fn resource_usage(&self) -> anyhow::Result<crate::ResourceUsageData> {
4234
self.resource_usage().map_err(Into::into)
4335
}
44-
fn clone_to_box(&self) -> Box<dyn Sandbox> {
45-
Box::new(self.clone())
46-
}
47-
48-
fn clone_into_box_any(&self) -> Box<dyn std::any::Any> {
49-
Box::new(self.clone())
36+
fn into_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync + 'static> {
37+
self
5038
}
5139
}
5240

@@ -89,36 +77,33 @@ impl<C: crate::ChildProcess> ChildProcess for C {
8977

9078
/// Type-erased `Backend`
9179
pub trait Backend: Send + Sync + 'static {
92-
fn new_sandbox(&self, options: crate::SandboxOptions) -> anyhow::Result<Box<dyn Sandbox>>;
80+
fn new_sandbox(&self, options: crate::SandboxOptions) -> anyhow::Result<Arc<dyn Sandbox>>;
9381
fn spawn(&self, options: ChildProcessOptions) -> anyhow::Result<Box<dyn ChildProcess>>;
9482
}
9583

9684
impl<B: crate::Backend> Backend for B {
97-
fn new_sandbox(&self, options: crate::SandboxOptions) -> anyhow::Result<Box<dyn Sandbox>> {
85+
fn new_sandbox(&self, options: crate::SandboxOptions) -> anyhow::Result<Arc<dyn Sandbox>> {
9886
let sb = <Self as crate::Backend>::new_sandbox(&self, options)?;
99-
Ok(Box::new(sb))
87+
Ok(Arc::new(sb))
10088
}
10189

10290
fn spawn(&self, options: ChildProcessOptions) -> anyhow::Result<Box<dyn ChildProcess>> {
103-
let down_sandbox = options
104-
.sandbox
105-
.clone_into_box_any()
106-
.downcast()
107-
.expect("sandbox type mismatch");
91+
let any_sandbox = options.sandbox.clone().into_arc_any();
92+
let down_sandbox = any_sandbox.downcast().expect("sandbox type mismatch");
10893
let down_options = crate::ChildProcessOptions {
10994
arguments: options.arguments,
11095
environment: options.environment,
11196
path: options.path,
11297
pwd: options.pwd,
11398
stdio: options.stdio,
114-
sandbox: *down_sandbox,
99+
sandbox: down_sandbox,
115100
};
116101
let cp = <Self as crate::Backend>::spawn(&self, down_options)?;
117102
Ok(Box::new(cp))
118103
}
119104
}
120105

121-
pub type ChildProcessOptions = crate::ChildProcessOptions<Box<dyn Sandbox>>;
106+
pub type ChildProcessOptions = crate::ChildProcessOptions<dyn Sandbox>;
122107

123108
/// Returns backend instance
124109
pub fn setup() -> anyhow::Result<Box<dyn Backend>> {

src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use std::{
2626
error::Error as StdError,
2727
fmt::Debug,
2828
io::{Read, Write},
29+
sync::Arc,
2930
time::Duration,
3031
};
3132

@@ -111,7 +112,7 @@ impl SandboxOptions {
111112
}
112113

113114
/// Represents highly-isolated sandbox
114-
pub trait Sandbox: Clone + Debug + Send + Sync + 'static {
115+
pub trait Sandbox: Debug + Send + Sync + 'static {
115116
type Error: StdError + Send + Sync + 'static;
116117
fn id(&self) -> String;
117118

@@ -227,11 +228,11 @@ pub struct StdioSpecification {
227228
/// This type should only be used by Backend implementations
228229
/// Use `Command` instead
229230
#[derive(Debug, Clone)]
230-
pub struct ChildProcessOptions<Sandbox> {
231+
pub struct ChildProcessOptions<Sandbox: ?Sized> {
231232
pub path: PathBuf,
232233
pub arguments: Vec<OsString>,
233234
pub environment: Vec<OsString>,
234-
pub sandbox: Sandbox,
235+
pub sandbox: Arc<Sandbox>,
235236
pub stdio: StdioSpecification,
236237
/// Child's working dir. Relative to `sandbox` isolation_root
237238
pub pwd: PathBuf,

src/linux.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ use std::{
2525
fs,
2626
os::unix::io::{IntoRawFd, RawFd},
2727
path::PathBuf,
28-
sync::atomic::{AtomicI64, Ordering},
29-
sync::Arc,
28+
sync::{
29+
atomic::{AtomicI64, Ordering},
30+
Arc,
31+
},
3032
};
3133

3234
pub type LinuxHandle = libc::c_int;
@@ -36,8 +38,8 @@ pub struct LinuxChildProcess {
3638
stdin: Option<LinuxWritePipe>,
3739
stdout: Option<LinuxReadPipe>,
3840
stderr: Option<LinuxReadPipe>,
39-
sandbox_ref: LinuxSandbox,
40-
/// Child pid, relative to sandbox namespace.
41+
sandbox_ref: Arc<LinuxSandbox>,
42+
4143
pid: Pid,
4244
/// FD of object which will be readable when child finishes.
4345
/// Wrapped in Option to catch user errors.

src/linux/sandbox.rs

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,8 @@ impl SandboxState {
4949
}
5050
}
5151

52-
#[derive(Clone)]
53-
pub struct LinuxSandbox(Arc<LinuxSandboxInner>);
54-
5552
#[repr(C)]
56-
struct LinuxSandboxInner {
53+
pub struct LinuxSandbox {
5754
id: String,
5855
options: SandboxOptions,
5956
zygote_sock: Mutex<Socket>,
@@ -76,12 +73,12 @@ struct LinuxSandboxDebugHelper<'a> {
7673
impl Debug for LinuxSandbox {
7774
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7875
let h = LinuxSandboxDebugHelper {
79-
id: &self.0.id,
80-
options: &self.0.options,
81-
zygote_sock: self.0.zygote_sock.lock().unwrap().as_raw_fd(),
82-
zygote_pid: self.0.zygote_pid,
83-
watchdog_chan: self.0.watchdog_chan,
84-
state: self.0.state.snapshot(),
76+
id: &self.id,
77+
options: &self.options,
78+
zygote_sock: self.zygote_sock.lock().unwrap().as_raw_fd(),
79+
zygote_pid: self.zygote_pid,
80+
watchdog_chan: self.watchdog_chan,
81+
state: self.state.snapshot(),
8582
};
8683

8784
h.fmt(f)
@@ -92,28 +89,28 @@ impl Sandbox for LinuxSandbox {
9289
type Error = Error;
9390

9491
fn id(&self) -> String {
95-
self.0.id.clone()
92+
self.id.clone()
9693
}
9794

9895
fn check_cpu_tle(&self) -> Result<bool, Error> {
9996
self.poll_state()?;
100-
Ok(self.0.state.was_cpu_tle.load(SeqCst))
97+
Ok(self.state.was_cpu_tle.load(SeqCst))
10198
}
10299

103100
fn check_real_tle(&self) -> Result<bool, Error> {
104101
self.poll_state()?;
105-
Ok(self.0.state.was_wall_tle.load(SeqCst))
102+
Ok(self.state.was_wall_tle.load(SeqCst))
106103
}
107104

108105
fn kill(&self) -> Result<(), Error> {
109-
jail_common::kill_sandbox(self.0.zygote_pid, &self.0.id, &self.0.cgroup_driver)
106+
jail_common::kill_sandbox(self.zygote_pid, &self.id, &self.cgroup_driver)
110107
.map_err(|err| Error::Io { cause: err })?;
111108
Ok(())
112109
}
113110

114111
fn resource_usage(&self) -> Result<crate::ResourceUsageData, Error> {
115-
let cpu_usage = self.0.cgroup_driver.get_cpu_usage(&self.0.id)?;
116-
let memory_usage = self.0.cgroup_driver.get_memory_usage(&self.0.id)?;
112+
let cpu_usage = self.cgroup_driver.get_cpu_usage(&self.id)?;
113+
let memory_usage = self.cgroup_driver.get_memory_usage(&self.id)?;
117114
Ok(crate::ResourceUsageData {
118115
memory: memory_usage,
119116
time: Some(cpu_usage),
@@ -132,7 +129,7 @@ impl LinuxSandbox {
132129
fn poll_state(&self) -> Result<(), Error> {
133130
for _ in 0..5 {
134131
let mut buf = [0; 4];
135-
let num_read = nix::unistd::read(self.0.watchdog_chan, &mut buf).or_else(|err| {
132+
let num_read = nix::unistd::read(self.watchdog_chan, &mut buf).or_else(|err| {
136133
if let Some(errno) = err.as_errno() {
137134
if errno as i32 == libc::EAGAIN {
138135
return Ok(0);
@@ -144,7 +141,7 @@ impl LinuxSandbox {
144141
break;
145142
}
146143
for ch in &buf[..num_read] {
147-
self.0.state.process_flag(*ch)?;
144+
self.state.process_flag(*ch)?;
148145
}
149146
}
150147

@@ -178,7 +175,7 @@ impl LinuxSandbox {
178175
};
179176
let startup_info = zygote::start_zygote(jail_options, &cgroup_driver)?;
180177

181-
let inner = LinuxSandboxInner {
178+
let sandbox = LinuxSandbox {
182179
id: jail_id,
183180
options,
184181
zygote_sock: Mutex::new(startup_info.socket),
@@ -191,7 +188,7 @@ impl LinuxSandbox {
191188
cgroup_driver,
192189
};
193190

194-
Ok(LinuxSandbox(Arc::new(inner)))
191+
Ok(sandbox)
195192
}
196193

197194
pub(crate) unsafe fn spawn_job(
@@ -200,7 +197,7 @@ impl LinuxSandbox {
200197
) -> Result<(jail_common::JobStartupInfo, RawFd), Error> {
201198
let q = jail_common::Query::Spawn(query.job_query.clone());
202199

203-
let mut sock = self.0.zygote_sock.lock().unwrap();
200+
let mut sock = self.zygote_sock.lock().unwrap();
204201

205202
// note that we ignore errors, because zygote can be already killed for some reason
206203
sock.send(&q).ok();
@@ -219,7 +216,7 @@ impl LinuxSandbox {
219216

220217
pub(crate) fn get_exit_code(&self, pid: Pid) -> ExitCode {
221218
let q = jail_common::Query::GetExitCode(jail_common::GetExitCodeQuery { pid });
222-
let mut sock = self.0.zygote_sock.lock().unwrap();
219+
let mut sock = self.zygote_sock.lock().unwrap();
223220
sock.send(&q).ok();
224221
match sock.recv::<i32>() {
225222
Ok(ec) => ExitCode(ec.into()),
@@ -230,24 +227,17 @@ impl LinuxSandbox {
230227

231228
impl Drop for LinuxSandbox {
232229
fn drop(&mut self) {
233-
match Arc::get_mut(&mut self.0) {
234-
// we are last Sandbox handle, so we can drop it
235-
Some(_) => (),
236-
// there are other handles, so we must not do anyhing
237-
None => return,
238-
};
239230
// Kill all processes.
240231
if let Err(err) = self.kill() {
241232
panic!("unable to kill sandbox: {}", err);
242233
}
243234
// Remove cgroups.
244235
if std::env::var("MINION_DEBUG_KEEP_CGROUPS").is_err() {
245-
self.0
246-
.cgroup_driver
247-
.drop_cgroup(&self.0.id, &["pids", "memory", "cpuacct"]);
236+
self.cgroup_driver
237+
.drop_cgroup(&self.id, &["pids", "memory", "cpuacct"]);
248238
}
249239

250240
// Close handles
251-
nix::unistd::close(self.0.watchdog_chan).ok();
241+
nix::unistd::close(self.watchdog_chan).ok();
252242
}
253243
}

src/linux/wait.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
//! Implements wait future
2-
use crate::{linux::util::Pid, linux::LinuxSandbox, ExitCode};
2+
use crate::{
3+
linux::{util::Pid, LinuxSandbox},
4+
ExitCode,
5+
};
36
use std::{
47
os::unix::io::RawFd,
58
pin::Pin,
9+
sync::Arc,
610
task::{Context, Poll},
711
};
812
use tokio::io::unix::AsyncFd;
@@ -36,15 +40,15 @@ pub struct WaitFuture {
3640
/// FD of underlying event source (either pidfd or unix socket)
3741
// TODO: use pipe instead of socket
3842
inner: AsyncFd<OwnedFd>,
39-
sandbox: LinuxSandbox,
43+
sandbox: Arc<LinuxSandbox>,
4044
pid: Pid,
4145
}
4246

4347
impl WaitFuture {
4448
pub(crate) fn new(
4549
fd: RawFd,
4650
pid: Pid,
47-
sandbox: LinuxSandbox,
51+
sandbox: Arc<LinuxSandbox>,
4852
) -> Result<Self, crate::linux::Error> {
4953
let inner = AsyncFd::new(OwnedFd(fd))?;
5054
Ok(WaitFuture {

0 commit comments

Comments
 (0)