use std::ffi::OsStr; use std::fmt::Debug; use std::io; #[cfg(not(windows))] use std::os::unix::process::CommandExt; #[cfg(windows)] use std::os::windows::process::CommandExt; use std::process::{Command, Stdio}; use log::{debug, warn}; #[cfg(windows)] use winapi::um::winbase::{CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW}; /// Start the daemon and log error on failure. pub fn start_daemon(program: &str, args: I) where I: IntoIterator + Debug + Copy, S: AsRef, { match spawn_daemon(program, args) { Ok(_) => debug!("Launched {} with args {:?}", program, args), Err(_) => warn!("Unable to launch {} with args {:?}", program, args), } } #[cfg(windows)] fn spawn_daemon(program: &str, args: I) -> io::Result<()> where I: IntoIterator + Copy, S: AsRef, { // Setting all the I/O handles to null and setting the // CREATE_NEW_PROCESS_GROUP and CREATE_NO_WINDOW has the effect // that console applications will run without opening a new // console window. Command::new(program) .args(args) .stdin(Stdio::null()) .stdout(Stdio::null()) .stderr(Stdio::null()) .creation_flags(CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW) .spawn() .map(|_| ()) } #[cfg(not(windows))] fn spawn_daemon(program: &str, args: I) -> io::Result<()> where I: IntoIterator + Copy, S: AsRef, { unsafe { Command::new(program) .args(args) .stdin(Stdio::null()) .stdout(Stdio::null()) .stderr(Stdio::null()) .pre_exec(|| { match libc::fork() { -1 => return Err(io::Error::last_os_error()), 0 => (), _ => libc::_exit(0), } if libc::setsid() == -1 { return Err(io::Error::last_os_error()); } Ok(()) }) .spawn()? .wait() .map(|_| ()) } }