stream_non_blocking/
stream_non_blocking.rs1use sandbox_rs::{SandboxBuilder, SeccompProfile, StreamChunk};
11use std::time::Duration;
12use tempfile::tempdir;
13
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 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 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 final_exit_code = exit_code;
62 break;
63 }
64 },
65 None => {
66 std::thread::sleep(Duration::from_millis(10));
68 }
69 }
70
71 if polling_attempts > 10000 {
73 println!("Safety timeout reached");
74 break;
75 }
76 }
77
78 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 result.check_seccomp_error()?;
90
91 Ok(())
92}