(cmd: &mut Command)
| 1546 | } |
| 1547 | |
| 1548 | fn spawn(cmd: &mut Command) -> Result<WasmtimeServe> { |
| 1549 | cmd.arg("--shutdown-addr=127.0.0.1:0"); |
| 1550 | cmd.stdin(Stdio::null()); |
| 1551 | cmd.stdout(Stdio::piped()); |
| 1552 | cmd.stderr(Stdio::piped()); |
| 1553 | let mut child = cmd.spawn()?; |
| 1554 | |
| 1555 | // Read the first few lines of stderr which will say which address |
| 1556 | // it's listening on. The first line is the shutdown line (with |
| 1557 | // `--shutdown-addr`) and the second is what `--addr` was bound to. |
| 1558 | // This is done to figure out what `:0` was bound to in the child |
| 1559 | // process. |
| 1560 | let mut line = String::new(); |
| 1561 | let mut stderr = BufReader::new(child.stderr.take().unwrap()); |
| 1562 | let mut read_addr_from_line = |prefix: &str| -> Result<SocketAddr> { |
| 1563 | stderr.read_line(&mut line)?; |
| 1564 | |
| 1565 | if !line.starts_with(prefix) { |
| 1566 | bail!("input line `{line}` didn't start with `{prefix}`"); |
| 1567 | } |
| 1568 | match line.find("127.0.0.1").and_then(|addr_start| { |
| 1569 | let addr = &line[addr_start..]; |
| 1570 | let addr_end = addr.find("/")?; |
| 1571 | addr[..addr_end].parse().ok() |
| 1572 | }) { |
| 1573 | Some(addr) => { |
| 1574 | line.truncate(0); |
| 1575 | Ok(addr) |
| 1576 | } |
| 1577 | None => bail!("failed to address from: {line}"), |
| 1578 | } |
| 1579 | }; |
| 1580 | let shutdown_addr = read_addr_from_line("Listening for shutdown"); |
| 1581 | let addr = read_addr_from_line("Serving HTTP on"); |
| 1582 | let (shutdown_addr, addr) = match (shutdown_addr, addr) { |
| 1583 | (Ok(a), Ok(b)) => (a, b), |
| 1584 | // If either failed kill the child and otherwise try to shepherd |
| 1585 | // along any contextual information we have. |
| 1586 | (Err(a), _) | (_, Err(a)) => { |
| 1587 | child.kill()?; |
| 1588 | child.wait()?; |
| 1589 | stderr.read_to_string(&mut line)?; |
| 1590 | return Err(a.context(line)); |
| 1591 | } |
| 1592 | }; |
| 1593 | let mut stdout = child.stdout.take().unwrap(); |
| 1594 | Ok(WasmtimeServe { |
| 1595 | stdout: Some(thread::spawn(move || { |
| 1596 | let mut dst = Vec::new(); |
| 1597 | stdout.read_to_end(&mut dst).map(|_| dst) |
| 1598 | })), |
| 1599 | |
| 1600 | stderr: Some(thread::spawn(move || { |
| 1601 | let mut dst = Vec::new(); |
| 1602 | stderr.read_to_end(&mut dst).map(|_| dst) |
| 1603 | })), |
| 1604 | |
| 1605 | child: Some(child), |
no test coverage detected