| 1614 | } |
| 1615 | |
| 1616 | fn _finish(&mut self) -> Result<(String, String)> { |
| 1617 | let mut child = self.child.take().unwrap(); |
| 1618 | |
| 1619 | // If the child process has already exited, then great! Otherwise |
| 1620 | // the server is still running and it shouldn't be possible to exit |
| 1621 | // until a shutdown signal is sent, so do that here. Make a TCP |
| 1622 | // connection to the shutdown port which is used as a shutdown |
| 1623 | // signal. |
| 1624 | if child.try_wait()?.is_none() { |
| 1625 | std::net::TcpStream::connect(&self.shutdown_addr) |
| 1626 | .context("failed to initiate graceful shutdown")?; |
| 1627 | } |
| 1628 | |
| 1629 | // Regardless of whether we just shut the server down or whether it |
| 1630 | // was already shut down (e.g. panicked or similar), wait for the |
| 1631 | // result here. The result should succeed (e.g. 0 exit status), and |
| 1632 | // if it did then the stdout/stderr are the caller's problem. |
| 1633 | let mut output = child.wait_with_output()?; |
| 1634 | output.stdout = self.stdout.take().unwrap().join().unwrap()?; |
| 1635 | output.stderr = self.stderr.take().unwrap().join().unwrap()?; |
| 1636 | if !output.status.success() { |
| 1637 | bail!("child failed {output:?}"); |
| 1638 | } |
| 1639 | |
| 1640 | Ok(( |
| 1641 | String::from_utf8_lossy(&output.stdout).into_owned(), |
| 1642 | String::from_utf8_lossy(&output.stderr).into_owned(), |
| 1643 | )) |
| 1644 | } |
| 1645 | |
| 1646 | /// Send a request to this server and wait for the response. |
| 1647 | async fn send_request(&self, req: http::Request<String>) -> Result<http::Response<String>> { |