SandboxResult

Struct SandboxResult 

Source
pub struct SandboxResult {
    pub exit_code: i32,
    pub signal: Option<i32>,
    pub timed_out: bool,
    pub memory_peak: u64,
    pub cpu_time_us: u64,
    pub wall_time_ms: u64,
}
Expand description

Sandbox execution result

Fields§

§exit_code: i32

Exit code

§signal: Option<i32>

Signal that killed process (if any)

§timed_out: bool

Whether timeout occurred

§memory_peak: u64

Memory usage in bytes

§cpu_time_us: u64

CPU time in microseconds

§wall_time_ms: u64

Wall clock time in seconds

Implementations§

Source§

impl SandboxResult

Source

pub fn killed_by_seccomp(&self) -> bool

Check if process was killed by seccomp (SIGSYS - signal 31) Returns true if exit code is 159 (128 + 31)

Source

pub fn seccomp_error(&self) -> Option<&'static str>

Get human-readable error message if process failed due to seccomp

Source

pub fn check_seccomp_error(&self) -> Result<&SandboxResult>

Convert to Result, returning error if process was killed by seccomp

Examples found in repository?
examples/stream_long_running.rs (line 71)
14fn main() -> sandbox_rs::Result<()> {
15    let tmp = tempdir().expect("Failed to create temp dir");
16
17    let mut sandbox = SandboxBuilder::new("long-running-example")
18        .memory_limit_str("512M")?
19        .cpu_limit_percent(100)
20        .timeout(Duration::from_secs(30))
21        .seccomp_profile(SeccompProfile::Unrestricted)
22        .root(tmp.path())
23        .build()?;
24
25    println!("Running bash script with streaming output...\n");
26
27    // Run a bash script that outputs multiple lines
28    let (result, stream) = sandbox.run_with_stream(
29        "/bin/bash",
30        &[
31            "-c",
32            "for i in {1..5}; do echo \"Line $i from stdout\"; echo \"Error line $i\" >&2; done",
33        ],
34    )?;
35
36    println!("Streaming output:");
37
38    let mut stdout_count = 0;
39    let mut stderr_count = 0;
40    let mut final_exit_code = result.exit_code;
41
42    for chunk in stream.into_iter() {
43        match chunk {
44            StreamChunk::Stdout(line) => {
45                stdout_count += 1;
46                println!("  [OUT #{}] {}", stdout_count, line);
47            }
48            StreamChunk::Stderr(line) => {
49                stderr_count += 1;
50                eprintln!("  [ERR #{}] {}", stderr_count, line);
51            }
52            StreamChunk::Exit {
53                exit_code,
54                signal: _,
55            } => {
56                println!("Process finished with exit code: {}", exit_code);
57                final_exit_code = exit_code;
58            }
59        }
60    }
61
62    let mut result = result;
63    result.exit_code = final_exit_code;
64
65    println!("\nSummary:");
66    println!("  Stdout lines: {}", stdout_count);
67    println!("  Stderr lines: {}", stderr_count);
68    println!("  Wall time: {} ms", result.wall_time_ms);
69    println!("  Exit code: {}", result.exit_code);
70
71    result.check_seccomp_error()?;
72
73    Ok(())
74}
More examples
Hide additional examples
examples/stream_basic.rs (line 63)
10fn main() -> sandbox_rs::Result<()> {
11    // Create a temporary directory for the sandbox
12    let tmp = tempdir().expect("Failed to create temp dir");
13
14    // Create a sandbox with streaming enabled
15    let mut sandbox = SandboxBuilder::new("stream-example")
16        .memory_limit_str("256M")?
17        .cpu_limit_percent(50)
18        .timeout(Duration::from_secs(30))
19        .root(tmp.path())
20        .build()?;
21
22    println!("Starting sandboxed process with streaming...\n");
23
24    // Run process with streaming
25    let (result, stream) = sandbox.run_with_stream("/bin/echo", &["Hello from sandbox!"])?;
26
27    println!("Process output (streaming):");
28
29    // Iterate through all output chunks
30    let mut final_exit_code = result.exit_code;
31    let mut final_signal = result.signal;
32
33    for chunk in stream.into_iter() {
34        match chunk {
35            StreamChunk::Stdout(line) => {
36                println!("[STDOUT] {}", line);
37            }
38            StreamChunk::Stderr(line) => {
39                eprintln!("[STDERR] {}", line);
40            }
41            StreamChunk::Exit { exit_code, signal } => {
42                println!("\nProcess exited with code: {}", exit_code);
43                if let Some(sig) = signal {
44                    println!("Killed by signal: {}", sig);
45                }
46                final_exit_code = exit_code;
47                final_signal = signal;
48            }
49        }
50    }
51
52    // Update result with the actual exit code from streaming
53    let mut result = result;
54    result.exit_code = final_exit_code;
55    result.signal = final_signal;
56
57    println!("\nExecution stats:");
58    println!("  Exit code: {}", result.exit_code);
59    println!("  Wall time: {} ms", result.wall_time_ms);
60    println!("  Memory peak: {} bytes", result.memory_peak);
61
62    // Check for seccomp errors and return error if found
63    result.check_seccomp_error()?;
64
65    Ok(())
66}
examples/stream_non_blocking.rs (line 89)
14fn main() -> sandbox_rs::Result<()> {
15    let tmp = tempdir().expect("Failed to create temp dir");
16
17    let mut sandbox = SandboxBuilder::new("non-blocking-example")
18        .memory_limit_str("256M")?
19        .cpu_limit_percent(50)
20        .seccomp_profile(SeccompProfile::Unrestricted)
21        .root(tmp.path())
22        .build()?;
23
24    println!("Running process with non-blocking stream reads...\n");
25
26    // Run a process that outputs slowly
27    let (result, stream) = sandbox.run_with_stream(
28        "/bin/bash",
29        &[
30            "-c",
31            "for i in {1..3}; do echo \"Message $i\"; sleep 0.1; done",
32        ],
33    )?;
34
35    println!("Non-blocking polling:");
36
37    let mut received_chunks = 0;
38    let mut polling_attempts = 0;
39    let mut final_exit_code = result.exit_code;
40
41    loop {
42        polling_attempts += 1;
43
44        // Try to read without blocking
45        match stream.try_recv()? {
46            Some(chunk) => match chunk {
47                StreamChunk::Stdout(line) => {
48                    println!("[STDOUT] {}", line);
49                    received_chunks += 1;
50                }
51                StreamChunk::Stderr(line) => {
52                    eprintln!("[STDERR] {}", line);
53                    received_chunks += 1;
54                }
55                StreamChunk::Exit {
56                    exit_code,
57                    signal: _,
58                } => {
59                    println!("Process exited with code: {}", exit_code);
60                    // Capture the real exit code from the stream
61                    final_exit_code = exit_code;
62                    break;
63                }
64            },
65            None => {
66                // No data available right now, we could do other work here
67                std::thread::sleep(Duration::from_millis(10));
68            }
69        }
70
71        // Safety limit to prevent infinite loop in case of issues
72        if polling_attempts > 10000 {
73            println!("Safety timeout reached");
74            break;
75        }
76    }
77
78    // Update result with the actual exit code from streaming
79    let mut result = result;
80    result.exit_code = final_exit_code;
81
82    println!("\nStatistics:");
83    println!("  Chunks received: {}", received_chunks);
84    println!("  Polling attempts: {}", polling_attempts);
85    println!("  Exit code: {}", result.exit_code);
86    println!("  Wall time: {} ms", result.wall_time_ms);
87
88    // Check for seccomp errors and return error if found
89    result.check_seccomp_error()?;
90
91    Ok(())
92}

Trait Implementations§

Source§

impl Clone for SandboxResult

Source§

fn clone(&self) -> SandboxResult

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SandboxResult

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.