1 // Copyright 2021-2022 Ian Jackson and contributors to Hippotat
2 // SPDX-License-Identifier: GPL-3.0-or-later
3 // There is NO WARRANTY.
7 type Tx = t_io::Split<t_io::BufReader<t_proc::ChildStdout>>;
11 pub rx: t_proc::ChildStdin,
12 stderr_task: JoinHandle<io::Result<()>>,
18 pub fn start(cmd: &str, ic_name: Option<String>) -> Self {
19 let mut child = tokio::process::Command::new("sh")
21 .stdin (process::Stdio::piped())
22 .stdout(process::Stdio::piped())
23 .stderr(process::Stdio::piped())
25 .spawn().context("spawn ipif")?;
27 let stderr = child.stderr.take().unwrap();
29 let stderr_task = task::spawn(async move {
30 let mut stderr = t_io::BufReader::new(stderr).lines();
31 while let Some(l) = stderr.next_line().await? {
32 error!("{}ipif stderr: {}",
33 OptionPrefixColon(ic_name.as_ref()),
39 let tx = child.stdout.take().unwrap();
40 let rx = child.stdin .take().unwrap();
41 let tx = t_io::BufReader::new(tx).split(SLIP_END);
51 pub async fn quitting(mut self, ic: Option<&InstanceConfig>) {
52 let icd = OptionPrefixColon(ic);
55 match self.child.wait().await {
56 Err(e) => error!("{}also, failed to await ipif child: {}", icd, e),
58 let stderr_timeout = Duration::from_millis(1000);
59 match tokio::time::timeout(stderr_timeout, self.stderr_task).await {
60 Err::<_,tokio::time::error::Elapsed>(_)
61 => warn!("{}ipif stderr task continues!", icd),
62 Ok(Err(e)) => error!("{}ipif stderr task crashed: {}", icd, e),
63 Ok(Ok(Err(e))) => error!("{}ipif stderr read failed: {}", icd, e),
64 Ok(Ok(Ok(()))) => { },
67 error!("{}ipif process failed: {}", icd, st);
76 pub async fn next_frame(tx: &mut Tx) -> Vec<u8> {
77 let data = tx.next_segment().await;
79 data?.ok_or_else(|| io::Error::from(io::ErrorKind::UnexpectedEof))
80 })().context("read from ipif")?