diff --git a/Cargo.lock b/Cargo.lock index 8a79ec0ff..964504e22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -440,6 +440,16 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +[[package]] +name = "close_fds" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bc416f33de9d59e79e57560f450d21ff8393adcf1cdfc3e6d8fb93d5f88a2ed" +dependencies = [ + "cfg-if 1.0.0", + "libc", +] + [[package]] name = "colorchoice" version = "1.0.0" @@ -2531,6 +2541,7 @@ dependencies = [ "cc", "chrono", "clap", + "close_fds", "daemonize", "directories", "encoding_rs", diff --git a/Cargo.toml b/Cargo.toml index d29cdbbb1..1226e2063 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -121,6 +121,7 @@ rouille = { version = "3.6", optional = true, default-features = false, features ] } syslog = { version = "6", optional = true } version-compare = { version = "0.1.1", optional = true } +close_fds = "0.3.2" [dev-dependencies] assert_cmd = "2.0.13" diff --git a/src/bin/sccache-dist/main.rs b/src/bin/sccache-dist/main.rs index 83d530060..6b4e670db 100644 --- a/src/bin/sccache-dist/main.rs +++ b/src/bin/sccache-dist/main.rs @@ -209,7 +209,7 @@ fn run(command: Command) -> Result { } }; - daemonize()?; + daemonize(None)?; let scheduler = Scheduler::new(); let http_scheduler = dist::http::Scheduler::new( public_addr, diff --git a/src/commands.rs b/src/commands.rs index 4de22e758..a32d5aa76 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -126,16 +126,6 @@ fn run_server_process(startup_timeout: Option) -> Result Result { Ok(f) } -/// If `SCCACHE_ERROR_LOG` is set, redirect stderr to it. -fn redirect_error_log(f: File) -> Result<()> { - debug!("redirecting stderr into {:?}", f); - redirect_stderr(f); - Ok(()) -} - /// Re-execute the current executable as a background server. #[cfg(windows)] fn run_server_process(startup_timeout: Option) -> Result { @@ -654,14 +637,15 @@ pub fn run_command(cmd: Command) -> Result { } Command::InternalStartServer => { trace!("Command::InternalStartServer"); + // If `SCCACHE_ERROR_LOG` is set, redirect stderr to it. if env::var("SCCACHE_ERROR_LOG").is_ok() { let f = create_error_log()?; + debug!("redirecting stderr into {:?}", f); // Can't report failure here, we're already daemonized. - daemonize()?; - redirect_error_log(f)?; + daemonize(Some(f))?; } else { // We aren't asking for a log file - daemonize()?; + daemonize(None)?; } server::start_server(config, &get_addr())?; } diff --git a/src/util.rs b/src/util.rs index 7174681d6..d8b1d578b 100644 --- a/src/util.rs +++ b/src/util.rs @@ -841,7 +841,7 @@ impl<'a> Hasher for HashToDigest<'a> { /// Pipe `cmd`'s stdio to `/dev/null`, unless a specific env var is set. #[cfg(not(windows))] -pub fn daemonize() -> Result<()> { +pub fn daemonize(log_file: Option) -> Result<()> { use crate::jobserver::discard_inherited_jobserver; use daemonize::Daemonize; use std::env; @@ -850,7 +850,16 @@ pub fn daemonize() -> Result<()> { match env::var("SCCACHE_NO_DAEMON") { Ok(ref val) if val == "1" => {} _ => { - Daemonize::new().start().context("failed to daemonize")?; + Daemonize::new() + .stderr(log_file + .map(|f| f.into_parts().0.into()) + .unwrap_or_else(|| daemonize::Stdio::devnull()) + ) + .start().context("failed to daemonize")?; + // Be extra-zealous and clase all non-stdio file descriptors. + unsafe { + close_fds::close_open_fds(3, &[]); + } } }