diff --git a/tools/hermit_proxy/src/daemon.rs b/tools/hermit_proxy/src/daemon.rs index 9e88ebf54..27a75759e 100644 --- a/tools/hermit_proxy/src/daemon.rs +++ b/tools/hermit_proxy/src/daemon.rs @@ -2,6 +2,7 @@ use std::os::unix::net::{UnixStream, UnixListener}; use std::path::Path; use std::result; use std::thread; +use std::process; use log; use log::{LogMetadata, LogRecord, SetLoggerError, LogLevel, LogLevelFilter}; use nix::unistd::{fork, ForkResult}; @@ -57,7 +58,11 @@ impl Connection { pub fn connect() -> Connection { if !Path::new("/tmp/hermit_daemon").exists() { match fork() { - Ok(ForkResult::Child) => daemon_handler(), + Ok(ForkResult::Child) => { + daemon_handler(); + + process::exit(0); + }, _ => {} } } @@ -76,7 +81,21 @@ impl Connection { let mut buf = Vec::new(); - self.socket.read_to_end(&mut buf).unwrap(); + if let Err(err) = self.socket.read_to_end(&mut buf) { + if let Action::KillDaemon = action { + return ActionResult::KillDaemon(Ok(())); + } + + panic!("The daemon seem to be crashed!"); + } + + if buf.len() == 0 { + if let Action::KillDaemon = action { + return ActionResult::KillDaemon(Ok(())); + } else { + panic!("he result was empty!"); + } + } deserialize(&buf).unwrap() } @@ -208,7 +227,7 @@ pub fn daemon_handler() { //for stream in listener.incoming() { // match stream { // Ok(mut stream) => { - loop { match listener.accept() { + 'outer: loop { match listener.accept() { Ok((mut stream, addr)) => { // loop { if let Ok(nread) = stream.read(&mut buf) { @@ -220,7 +239,7 @@ pub fn daemon_handler() { let ret = match action { Action::KillDaemon => { fs::remove_file("/tmp/hermit_daemon").unwrap(); - break; + break 'outer; }, Action::CreateIsle(path, specs) => ActionResult::CreateIsle(state.create_isle(path,specs)), Action::List => ActionResult::List(state.list()), diff --git a/tools/hermit_proxy/src/hermit/qemu.rs b/tools/hermit_proxy/src/hermit/qemu.rs index 78823e44f..700882806 100644 --- a/tools/hermit_proxy/src/hermit/qemu.rs +++ b/tools/hermit_proxy/src/hermit/qemu.rs @@ -5,6 +5,8 @@ use std::fs::File; use std::io::Read; use std::process::{ChildStdout, ChildStderr}; use std::thread; +use std::os::unix::net::UnixStream; +use std::io::Write; use hermit::{Isle, IsleParameterQEmu}; use hermit::utils; @@ -32,6 +34,7 @@ impl QEmu { let mut child = QEmu::start_with(path, mem_size, num_cpus, additional, &tmpf, &pidf)?.spawn().expect("Couldn't find qemu binary!"); let stdout = child.stdout.take().unwrap(); let stderr = child.stderr.take().unwrap(); + println!("{}", pidf); Ok(QEmu { socket: Some(Socket::new_qemu()), @@ -39,17 +42,18 @@ impl QEmu { stdout: stdout, stderr: stderr, tmp_file: tmpf, - pid_file: pidf + pid_file: pidf, }) } pub fn start_with(path: &str, mem_size: u64, num_cpus: u32, add: IsleParameterQEmu, tmp_file: &str, pid_file: &str) -> Result { let hostfwd = format!("user,hostfwd=tcp:127.0.0.1:{}-:{}", add.port, add.port); - let monitor_str = format!("telnet:127.0.0.1:{},server,nowait", add.port+1); + //let monitor_str = format!("telnet:127.0.0.1:{},server,nowait", add.port+1); + let monitor_str = format!("unix:{}_monitor,server,nowait", pid_file); let chardev = format!("file,id=gnc0,path={}",&tmp_file); let freq = format!("\"-freq{} -proxy\"",(utils::cpufreq().unwrap()/1000).to_string()); let num_cpus = num_cpus.to_string(); - let mem_size = mem_size.to_string(); + let mem_size = format!("{}B", mem_size); let exe = env::current_exe().unwrap(); let name = exe.to_str().unwrap(); @@ -86,10 +90,8 @@ impl QEmu { args.push("host"); } - if add.monitor { - args.push("-monitor"); - args.push(&monitor_str); - } + args.push("-monitor"); + args.push(&monitor_str); if add.should_debug { args.push("-s"); @@ -100,14 +102,12 @@ impl QEmu { args.push("dump"); } - debug!("Execute {} with args {:#?}", add.binary, args); - + debug!("Execute {} with {}", add.binary, args.join(" ")); let mut cmd = Command::new(add.binary); cmd.args(args).stdout(Stdio::piped()).stderr(Stdio::piped()); - Ok(cmd) } @@ -120,6 +120,22 @@ impl QEmu { (stdout, stderr) } + + pub fn send_cmd(&self, cmd: &str) -> Result { + let file = format!("{}_monitor", self.pid_file); + + let mut control = UnixStream::connect(&file) + .map_err(|_| Error::InvalidFile(file.clone()))?; + + control.write_all(cmd.as_bytes()) + .map_err(|_| Error::InvalidFile(file))?; + + let mut buf = String::new(); + + control.read_to_string(&mut buf); + + Ok(buf) + } } impl Isle for QEmu { @@ -155,11 +171,15 @@ impl Isle for QEmu { } fn stop(&mut self) -> Result { + self.send_cmd("system_powerdown")?; + Ok(0) } fn is_running(&mut self) -> Result { - Ok(true) + let state = self.send_cmd("info status")?; + + Ok(state == "running") } } diff --git a/tools/hermit_proxy/src/hermit/socket.rs b/tools/hermit_proxy/src/hermit/socket.rs index 29e3adb55..dc0694d48 100644 --- a/tools/hermit_proxy/src/hermit/socket.rs +++ b/tools/hermit_proxy/src/hermit/socket.rs @@ -31,19 +31,10 @@ impl Socket { } pub fn connect(&self) -> Socket { - let mut stream = match *self { - Socket::QEmu => TcpStream::connect(("127.0.0.1", 0x494E)).unwrap(), - Socket::Multi(id) => TcpStream::connect((format!("127.0.0.{}", id).as_ref(), 0x494E)).unwrap(), - _ => panic!("") - }; - - debug!("Connected to {}", stream.peer_addr().unwrap()); - + // prepare the initializing struct let length: usize = 4 + env::args().skip(2).map(|x| 4+x.len()).sum::()+ 4 + env::vars().map(|(x,y)| 5 + x.len()+ y.len()).sum::(); - let mut buf = Cursor::new(vec![0u8;length]); buf.write_u32::(HERMIT_MAGIC); - // send all arguments (skip first) buf.write_u32::(env::args().count() as u32 - 2); for key in env::args().skip(2) { @@ -59,8 +50,37 @@ impl Socket { buf.write(tmp.as_bytes()); } - stream.write(buf.get_ref()); + let mut stream; + loop { + match *self { + Socket::QEmu => { + match TcpStream::connect(("127.0.0.1", 0x494E)) { + Ok(mut s) => { + match s.write(buf.get_ref()) { + Ok(_) => { stream = s; break; }, + Err(_) => {} + } + }, + Err(_) => {} + } + }, + Socket::Multi(id) => { + match TcpStream::connect((format!("127.0.0.{}", id).as_ref(), 0x494E)) { + Ok(mut s) => { + match s.write(buf.get_ref()) { + Ok(_) => { stream = s; break; }, + Err(_) => {} + } + }, + Err(_) => {} + } + }, + _ => panic!("") + } + } + + debug!("Connected to {}", stream.peer_addr().unwrap()); debug!("Transmitted environment and arguments with length {}", length); Socket::Connected { stream: stream, stdout: String::new(), stderr: String::new() }