diff --git a/src/server.rs b/src/server.rs index 3ebc60a..a8ad1f1 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,7 +1,7 @@ -use crate::server::utils::{get_free_port, wait_for_port}; +use crate::server::utils::{get_free_port, wait_for_server}; use mktemp::Temp; use std::io::{self, Cursor, Read}; -use std::process::{Child, Stdio}; +use std::process::{Child, ExitStatus, Stdio}; use thiserror::Error; use zip::{result::ZipError, ZipArchive}; @@ -13,6 +13,15 @@ pub enum Error { #[error("Get an available port failed")] GetFreePort(#[source] io::Error), + #[error("Server exit with `{status}`")] + ServerExitWithStatus { status: ExitStatus }, + + #[error("Server exit with `{status}` :\n{msg}")] + ServerExitWithError { status: ExitStatus, msg: String }, + + #[error("Error append during check grammalecte-server status")] + ServerCheckStatus(#[source] io::Error), + #[error("Port {port} did not open in time!")] WaitPortOpen { port: u16 }, @@ -80,16 +89,16 @@ impl EmbeddedServer { log::info!("Will execute file {}", server_file); // Start server - let child = std::process::Command::new("/usr/bin/python3") + let mut child = std::process::Command::new("/usr/bin/python3") .arg(server_file) .arg("-p") .arg(port.to_string()) .stdout(Stdio::null()) - .stderr(Stdio::null()) + .stderr(Stdio::piped()) .spawn() .map_err(Error::StartServerProcess)?; - wait_for_port(port)?; + wait_for_server(&mut child, port)?; Ok(Self { _srv_dir: dest, @@ -111,9 +120,11 @@ impl Drop for EmbeddedServer { } mod utils { - use std::time::Duration; - use super::Error; + use std::fmt::Write; + use std::io::{BufRead, BufReader}; + use std::process::Child; + use std::time::Duration; /// Get a free port pub fn get_free_port() -> u16 { @@ -130,8 +141,9 @@ mod utils { port } - pub fn wait_for_port(port: u16) -> Result<(), Error> { + pub fn wait_for_server(child: &mut Child, port: u16) -> Result<(), Error> { for _ in 0..50 { + check_server(child)?; if port_scanner::scan_port(port) { return Ok(()); } @@ -140,4 +152,28 @@ mod utils { Err(Error::WaitPortOpen { port }) } + + fn check_server(child: &mut Child) -> Result<(), Error> { + match child.try_wait().map_err(Error::ServerCheckStatus)? { + None => Ok(()), // Continue + Some(status) => { + if let Some(err) = child.stderr.take() { + let mut msg = format!("grammalecte-server exit with `{status}`"); + writeln!(&mut msg, " :").unwrap(); + let err = BufReader::new(err); + err.lines().for_each(|line| match line { + Ok(line) => { + writeln!(&mut msg, "\t{}", line).unwrap(); + } + Err(err) => { + writeln!(&mut msg, "__{err:?}").unwrap(); + } + }); + Err(Error::ServerExitWithError { status, msg }) + } else { + Err(Error::ServerExitWithStatus { status }) + } + } + } + } }