fn start_listener(cb: T) { let mut child = Command::new("jupyter") .arg("lab") .arg("--no-browser") .stdout(Stdio::piped()) .spawn() .expect("Failed to start ping process"); println!("Started process: {}", child.id()); thread::spawn(move || { let mut f = BufReader::new(child.stdout.unwrap()); loop { let mut buf = String::new(); match f.read_line(&mut buf) { Ok(_) => { cb(&buf); } Err(e) => println!("an error!: {:?}", e), } } child.wait().expect("Failed to wait on child"); }); } fn main() { start_listener(|s| { println!("Got this back: {}", s); }); sleep(Duration::from_secs(5)); println!("Done!"); } fn start_process(sender: Sender, receiver: Receiver) { let mut child = Command::new("jupyter") .arg("lab") .arg("--no-browser") .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() .expect("Failed to start process"); println!("Started process: {}", child.id()); let child_stdout = child.stdout.take().unwrap(); let child_stdin = child.stdin.take().unwrap(); let sender_clone = sender.clone(); thread::spawn(move || { let mut f = BufReader::new(child_stdout); loop { let mut buf = String::new(); match f.read_line(&mut buf) { Ok(_) => { sender_clone.send(buf).unwrap(); } Err(e) => { println!("an error!: {:?}", e); break; } } } }); thread::spawn(move || { let stdin = child_stdin; for line in receiver { stdin.write_all(line.as_bytes()).unwrap(); } }); } // ... (rest of your code)