ProcessStream

Struct ProcessStream 

Source
pub struct ProcessStream { /* private fields */ }
Expand description

Handle for receiving process output streams

Implementations§

Source§

impl ProcessStream

Source

pub fn new() -> (ProcessStreamWriter, Self)

Create new process stream handler

Source

pub fn recv(&self) -> Result<Option<StreamChunk>>

Receive next chunk from process streams

Source

pub fn try_recv(&self) -> Result<Option<StreamChunk>>

Try to receive next chunk without blocking

Examples found in repository?
examples/stream_non_blocking.rs (line 45)
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 Default for ProcessStream

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl IntoIterator for ProcessStream

Source§

type Item = StreamChunk

The type of the elements being iterated over.
Source§

type IntoIter = StreamIter

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. 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> 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, 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.