Skip to content

Commit dbd66c2

Browse files
authored
Merge pull request #16 from jjs-dev/errors
Refactor errors
2 parents d2824a0 + 859cf10 commit dbd66c2

File tree

14 files changed

+182
-161
lines changed

14 files changed

+182
-161
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ procfs = "0.7.8"
1515
nix = {git = "https://github.com/nix-rust/nix"}
1616
backtrace = "0.3.46"
1717
thiserror = "1.0.19"
18+
anyhow = "1.0.32"
1819

1920
[workspace]
2021
members = ["minion-ffi", ".", "minion-tests", "minion-cli"]

src/command.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl Command {
4949
pub fn spawn(
5050
&self,
5151
backend: &dyn erased::Backend,
52-
) -> crate::Result<Box<dyn erased::ChildProcess>> {
52+
) -> anyhow::Result<Box<dyn erased::ChildProcess>> {
5353
let options = self
5454
.build()
5555
.expect("spawn() was requested, but required fields were not set");

src/erased.rs

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
/// Type-erased `Sandbox`
88
pub trait Sandbox: std::fmt::Debug {
99
fn id(&self) -> String;
10-
fn check_cpu_tle(&self) -> crate::Result<bool>;
11-
fn check_real_tle(&self) -> crate::Result<bool>;
12-
fn kill(&self) -> crate::Result<()>;
13-
fn resource_usage(&self) -> crate::Result<crate::ResourceUsageData>;
10+
fn check_cpu_tle(&self) -> anyhow::Result<bool>;
11+
fn check_real_tle(&self) -> anyhow::Result<bool>;
12+
fn kill(&self) -> anyhow::Result<()>;
13+
fn resource_usage(&self) -> anyhow::Result<crate::ResourceUsageData>;
1414
#[doc(hidden)]
1515
fn clone_to_box(&self) -> Box<dyn Sandbox>;
1616
#[doc(hidden)]
@@ -27,17 +27,17 @@ impl<S: crate::Sandbox> Sandbox for S {
2727
fn id(&self) -> String {
2828
self.id()
2929
}
30-
fn check_cpu_tle(&self) -> crate::Result<bool> {
31-
self.check_cpu_tle()
30+
fn check_cpu_tle(&self) -> anyhow::Result<bool> {
31+
self.check_cpu_tle().map_err(Into::into)
3232
}
33-
fn check_real_tle(&self) -> crate::Result<bool> {
34-
self.check_real_tle()
33+
fn check_real_tle(&self) -> anyhow::Result<bool> {
34+
self.check_real_tle().map_err(Into::into)
3535
}
36-
fn kill(&self) -> crate::Result<()> {
37-
self.kill()
36+
fn kill(&self) -> anyhow::Result<()> {
37+
self.kill().map_err(Into::into)
3838
}
39-
fn resource_usage(&self) -> crate::Result<crate::ResourceUsageData> {
40-
self.resource_usage()
39+
fn resource_usage(&self) -> anyhow::Result<crate::ResourceUsageData> {
40+
self.resource_usage().map_err(Into::into)
4141
}
4242
fn clone_to_box(&self) -> Box<dyn Sandbox> {
4343
Box::new(self.clone())
@@ -50,21 +50,21 @@ impl<S: crate::Sandbox> Sandbox for S {
5050

5151
/// Type-erased `ChildProcess`
5252
pub trait ChildProcess {
53-
fn get_exit_code(&self) -> crate::Result<Option<i64>>;
53+
fn get_exit_code(&self) -> anyhow::Result<Option<i64>>;
5454
fn stdin(&mut self) -> Option<Box<dyn std::io::Write + Send + Sync + 'static>>;
5555
fn stdout(&mut self) -> Option<Box<dyn std::io::Read + Send + Sync + 'static>>;
5656
fn stderr(&mut self) -> Option<Box<dyn std::io::Read + Send + Sync + 'static>>;
5757
fn wait_for_exit(
5858
&self,
5959
timeout: Option<std::time::Duration>,
60-
) -> crate::Result<crate::WaitOutcome>;
61-
fn poll(&self) -> crate::Result<()>;
62-
fn is_finished(&self) -> crate::Result<bool>;
60+
) -> anyhow::Result<crate::WaitOutcome>;
61+
fn poll(&self) -> anyhow::Result<()>;
62+
fn is_finished(&self) -> anyhow::Result<bool>;
6363
}
6464

6565
impl<C: crate::ChildProcess> ChildProcess for C {
66-
fn get_exit_code(&self) -> crate::Result<Option<i64>> {
67-
self.get_exit_code()
66+
fn get_exit_code(&self) -> anyhow::Result<Option<i64>> {
67+
self.get_exit_code().map_err(Into::into)
6868
}
6969
fn stdin(&mut self) -> Option<Box<dyn std::io::Write + Send + Sync + 'static>> {
7070
match self.stdin() {
@@ -87,30 +87,30 @@ impl<C: crate::ChildProcess> ChildProcess for C {
8787
fn wait_for_exit(
8888
&self,
8989
timeout: Option<std::time::Duration>,
90-
) -> crate::Result<crate::WaitOutcome> {
91-
self.wait_for_exit(timeout)
90+
) -> anyhow::Result<crate::WaitOutcome> {
91+
self.wait_for_exit(timeout).map_err(Into::into)
9292
}
93-
fn poll(&self) -> crate::Result<()> {
94-
self.poll()
93+
fn poll(&self) -> anyhow::Result<()> {
94+
self.poll().map_err(Into::into)
9595
}
96-
fn is_finished(&self) -> crate::Result<bool> {
97-
self.is_finished()
96+
fn is_finished(&self) -> anyhow::Result<bool> {
97+
self.is_finished().map_err(Into::into)
9898
}
9999
}
100100

101101
/// Type-erased `Backend`
102102
pub trait Backend {
103-
fn new_sandbox(&self, options: crate::SandboxOptions) -> crate::Result<Box<dyn Sandbox>>;
104-
fn spawn(&self, options: ChildProcessOptions) -> crate::Result<Box<dyn ChildProcess>>;
103+
fn new_sandbox(&self, options: crate::SandboxOptions) -> anyhow::Result<Box<dyn Sandbox>>;
104+
fn spawn(&self, options: ChildProcessOptions) -> anyhow::Result<Box<dyn ChildProcess>>;
105105
}
106106

107107
impl<B: crate::Backend> Backend for B {
108-
fn new_sandbox(&self, options: crate::SandboxOptions) -> crate::Result<Box<dyn Sandbox>> {
108+
fn new_sandbox(&self, options: crate::SandboxOptions) -> anyhow::Result<Box<dyn Sandbox>> {
109109
let sb = <Self as crate::Backend>::new_sandbox(&self, options)?;
110110
Ok(Box::new(sb))
111111
}
112112

113-
fn spawn(&self, options: ChildProcessOptions) -> crate::Result<Box<dyn ChildProcess>> {
113+
fn spawn(&self, options: ChildProcessOptions) -> anyhow::Result<Box<dyn ChildProcess>> {
114114
let down_sandbox = options
115115
.sandbox
116116
.clone_into_box_any()
@@ -132,7 +132,7 @@ impl<B: crate::Backend> Backend for B {
132132
pub type ChildProcessOptions = crate::ChildProcessOptions<Box<dyn Sandbox>>;
133133

134134
/// Returns backend instance
135-
pub fn setup() -> crate::Result<Box<dyn Backend>> {
135+
pub fn setup() -> anyhow::Result<Box<dyn Backend>> {
136136
Ok(Box::new(crate::linux::LinuxBackend::new(
137137
crate::linux::Settings::new(),
138138
)?))

src/lib.rs

Lines changed: 19 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use serde::{Deserialize, Serialize};
2020
pub use crate::linux::{LinuxBackend, LinuxChildProcess, LinuxSandbox};
2121

2222
use std::{
23+
error::Error as StdError,
2324
fmt::Debug,
2425
io::{Read, Write},
2526
time::Duration,
@@ -42,10 +43,14 @@ pub fn check() -> Option<String> {
4243

4344
/// Represents way of isolation
4445
pub trait Backend: Debug + Send + Sync {
45-
type Sandbox: Sandbox;
46-
type ChildProcess: ChildProcess;
47-
fn new_sandbox(&self, options: SandboxOptions) -> Result<Self::Sandbox>;
48-
fn spawn(&self, options: ChildProcessOptions<Self::Sandbox>) -> Result<Self::ChildProcess>;
46+
type Error: StdError + Send + Sync + 'static;
47+
type Sandbox: Sandbox<Error = Self::Error>;
48+
type ChildProcess: ChildProcess<Error = Self::Error>;
49+
fn new_sandbox(&self, options: SandboxOptions) -> Result<Self::Sandbox, Self::Error>;
50+
fn spawn(
51+
&self,
52+
options: ChildProcessOptions<Self::Sandbox>,
53+
) -> Result<Self::ChildProcess, Self::Error>;
4954
}
5055

5156
pub use command::Command;
@@ -116,20 +121,21 @@ impl SandboxOptions {
116121

117122
/// Represents highly-isolated sandbox
118123
pub trait Sandbox: Clone + Debug + 'static {
124+
type Error: StdError + Send + Sync + 'static;
119125
fn id(&self) -> String;
120126

121127
/// Returns true if sandbox exceeded CPU time limit
122-
fn check_cpu_tle(&self) -> Result<bool>;
128+
fn check_cpu_tle(&self) -> Result<bool, Self::Error>;
123129

124130
/// Returns true if sandbox exceeded wall-clock time limit
125-
fn check_real_tle(&self) -> Result<bool>;
131+
fn check_real_tle(&self) -> Result<bool, Self::Error>;
126132

127133
/// Kills all processes in sandbox.
128134
/// Probably, subsequent `spawn` requests will fail.
129-
fn kill(&self) -> Result<()>;
135+
fn kill(&self) -> Result<(), Self::Error>;
130136

131137
/// Returns information about resource usage by total sandbox
132-
fn resource_usage(&self) -> Result<ResourceUsageData>;
138+
fn resource_usage(&self) -> Result<ResourceUsageData, Self::Error>;
133139
}
134140

135141
/// Configures stdin for child
@@ -240,72 +246,11 @@ pub struct ChildProcessOptions<Sandbox> {
240246
pub pwd: PathBuf,
241247
}
242248

243-
mod errors {
244-
#[derive(Eq, PartialEq)]
245-
pub enum ErrorKind {
246-
/// This error typically means that isolated process tried to break its sandbox
247-
Sandbox,
248-
/// Bug in code, using minion, or in minion itself
249-
System,
250-
}
251-
252-
#[derive(Debug, thiserror::Error)]
253-
#[non_exhaustive]
254-
pub enum Error {
255-
#[error("requested operation is not supported by backend")]
256-
NotSupported,
257-
#[error("system call failed in undesired fashion (error code {})", code)]
258-
Syscall { code: i32 },
259-
#[error("io error")]
260-
Io {
261-
#[from]
262-
source: std::io::Error,
263-
},
264-
#[error("sandbox interaction failed")]
265-
Sandbox,
266-
#[error("unknown error")]
267-
Unknown,
268-
}
269-
270-
impl Error {
271-
pub fn kind(&self) -> ErrorKind {
272-
match self {
273-
Error::NotSupported => ErrorKind::System,
274-
Error::Syscall { .. } => ErrorKind::System,
275-
Error::Io { .. } => ErrorKind::System,
276-
Error::Sandbox => ErrorKind::Sandbox,
277-
Error::Unknown => ErrorKind::System,
278-
}
279-
}
280-
281-
pub fn is_system(&self) -> bool {
282-
self.kind() == ErrorKind::System
283-
}
284-
285-
pub fn is_sandbox(&self) -> bool {
286-
self.kind() == ErrorKind::Sandbox
287-
}
288-
}
289-
290-
impl From<nix::Error> for Error {
291-
fn from(err: nix::Error) -> Self {
292-
if let Some(errno) = err.as_errno() {
293-
Error::Syscall { code: errno as i32 }
294-
} else {
295-
Error::Unknown
296-
}
297-
}
298-
}
299-
}
300-
301-
pub use errors::Error;
302249
use std::{
303250
ffi::OsString,
304251
path::{Path, PathBuf},
305252
};
306253

307-
pub type Result<T> = std::result::Result<T, Error>;
308-
309254
/// May be returned when process was killed
310255
pub const EXIT_CODE_KILLED: i64 = 0x7eaddeadbeeff00d;
311256

@@ -324,12 +269,13 @@ pub enum WaitOutcome {
324269

325270
/// Represents child process.
326271
pub trait ChildProcess: Debug + 'static {
272+
type Error: StdError + Send + Sync + 'static;
327273
/// Represents pipe from current process to isolated
328274
type PipeIn: Write + Send + Sync + 'static;
329275
/// Represents pipe from isolated process to current
330276
type PipeOut: Read + Send + Sync + 'static;
331277
/// Returns exit code, if process had exited by the moment of call, or None otherwise.
332-
fn get_exit_code(&self) -> Result<Option<i64>>;
278+
fn get_exit_code(&self) -> Result<Option<i64>, Self::Error>;
333279

334280
/// Returns writeable stream, connected to child stdin
335281
///
@@ -358,12 +304,12 @@ pub trait ChildProcess: Debug + 'static {
358304

359305
/// Waits for child process exit with timeout.
360306
/// If timeout is None, `wait_for_exit` will block until child has exited
361-
fn wait_for_exit(&self, timeout: Option<Duration>) -> Result<WaitOutcome>;
307+
fn wait_for_exit(&self, timeout: Option<Duration>) -> Result<WaitOutcome, Self::Error>;
362308

363309
/// Refreshes information about process
364-
fn poll(&self) -> Result<()>;
310+
fn poll(&self) -> Result<(), Self::Error>;
365311

366312
/// Returns whether child process has exited by the moment of call
367313
/// This function doesn't blocks on waiting (see `wait_for_exit`).
368-
fn is_finished(&self) -> Result<bool>;
314+
fn is_finished(&self) -> Result<bool, Self::Error>;
369315
}

0 commit comments

Comments
 (0)