Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 18 additions & 15 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use std::io::{self, Write};
use std::os::unix::process::ExitStatusExt;
use std::path::Path;
use std::process;
use std::time::Duration;
use strip_ansi_escapes::Writer;
use tokio::io::AsyncReadExt;
use tokio::runtime::Runtime;
Expand All @@ -43,7 +44,7 @@ use crate::errors::*;
pub const DEFAULT_PORT: u16 = 4226;

/// The number of milliseconds to wait for server startup.
const SERVER_STARTUP_TIMEOUT_MS: u32 = 10000;
const SERVER_STARTUP_TIMEOUT: Duration = Duration::from_millis(10000);

/// Get the port on which the server should listen.
fn get_port() -> u16 {
Expand Down Expand Up @@ -78,9 +79,7 @@ async fn read_server_startup_status<R: AsyncReadExt + Unpin>(
/// Re-execute the current executable as a background server, and wait
/// for it to start up.
#[cfg(not(windows))]
fn run_server_process() -> Result<ServerStartup> {
use std::time::Duration;

fn run_server_process(startup_timeout: Option<Duration>) -> Result<ServerStartup> {
trace!("run_server_process");
let tempdir = tempfile::Builder::new().prefix("sccache").tempdir()?;
let socket_path = tempdir.path().join("sock");
Expand All @@ -101,7 +100,7 @@ fn run_server_process() -> Result<ServerStartup> {
read_server_startup_status(socket).await
};

let timeout = Duration::from_millis(SERVER_STARTUP_TIMEOUT_MS.into());
let timeout = startup_timeout.unwrap_or(SERVER_STARTUP_TIMEOUT);
runtime.block_on(async move {
match tokio::time::timeout(timeout, startup).await {
Ok(result) => result,
Expand Down Expand Up @@ -159,12 +158,11 @@ fn redirect_error_log(f: File) -> Result<()> {

/// Re-execute the current executable as a background server.
#[cfg(windows)]
fn run_server_process() -> Result<ServerStartup> {
fn run_server_process(startup_timeout: Option<Duration>) -> Result<ServerStartup> {
use futures::StreamExt;
use std::mem;
use std::os::windows::ffi::OsStrExt;
use std::ptr;
use std::time::Duration;
use uuid::Uuid;
use winapi::shared::minwindef::{DWORD, FALSE, LPVOID, TRUE};
use winapi::um::handleapi::CloseHandle;
Expand Down Expand Up @@ -256,7 +254,7 @@ fn run_server_process() -> Result<ServerStartup> {
read_server_startup_status(socket?).await
};

let timeout = Duration::from_millis(SERVER_STARTUP_TIMEOUT_MS.into());
let timeout = startup_timeout.unwrap_or(SERVER_STARTUP_TIMEOUT);
runtime.block_on(async move {
match tokio::time::timeout(timeout, startup).await {
Ok(result) => result,
Expand All @@ -266,7 +264,10 @@ fn run_server_process() -> Result<ServerStartup> {
}

/// Attempt to connect to an sccache server listening on `port`, or start one if no server is running.
fn connect_or_start_server(port: u16) -> Result<ServerConnection> {
fn connect_or_start_server(
port: u16,
startup_timeout: Option<Duration>,
) -> Result<ServerConnection> {
trace!("connect_or_start_server({})", port);
match connect_to_server(port) {
Ok(server) => Ok(server),
Expand All @@ -276,7 +277,7 @@ fn connect_or_start_server(port: u16) -> Result<ServerConnection> {
{
// If the connection was refused we probably need to start
// the server.
match run_server_process()? {
match run_server_process(startup_timeout)? {
ServerStartup::Ok { port: actualport } => {
if port != actualport {
// bail as the next connect_with_retry will fail
Expand Down Expand Up @@ -578,11 +579,12 @@ pub fn run_command(cmd: Command) -> Result<i32> {
// Config isn't required for all commands, but if it's broken then we should flag
// it early and loudly.
let config = &Config::load()?;
let startup_timeout = config.server_startup_timeout;

match cmd {
Command::ShowStats(fmt) => {
trace!("Command::ShowStats({:?})", fmt);
let srv = connect_or_start_server(get_port())?;
let srv = connect_or_start_server(get_port(), startup_timeout)?;
let stats = request_stats(srv).context("failed to get stats from server")?;
match fmt {
StatsFormat::Text => stats.print(),
Expand All @@ -605,7 +607,8 @@ pub fn run_command(cmd: Command) -> Result<i32> {
Command::StartServer => {
trace!("Command::StartServer");
println!("sccache: Starting the server...");
let startup = run_server_process().context("failed to start server process")?;
let startup =
run_server_process(startup_timeout).context("failed to start server process")?;
match startup {
ServerStartup::Ok { port } => {
if port != DEFAULT_PORT {
Expand All @@ -626,7 +629,7 @@ pub fn run_command(cmd: Command) -> Result<i32> {
}
Command::ZeroStats => {
trace!("Command::ZeroStats");
let conn = connect_or_start_server(get_port())?;
let conn = connect_or_start_server(get_port(), startup_timeout)?;
let stats = request_zero_stats(conn).context("couldn't zero stats on server")?;
stats.print();
}
Expand Down Expand Up @@ -688,7 +691,7 @@ pub fn run_command(cmd: Command) -> Result<i32> {
),
Command::DistStatus => {
trace!("Command::DistStatus");
let srv = connect_or_start_server(get_port())?;
let srv = connect_or_start_server(get_port(), startup_timeout)?;
let status =
request_dist_status(srv).context("failed to get dist-status from server")?;
serde_json::to_writer(&mut io::stdout(), &status)?;
Expand Down Expand Up @@ -726,7 +729,7 @@ pub fn run_command(cmd: Command) -> Result<i32> {
} => {
trace!("Command::Compile {{ {:?}, {:?}, {:?} }}", exe, cmdline, cwd);
let jobserver = unsafe { Client::new() };
let conn = connect_or_start_server(get_port())?;
let conn = connect_or_start_server(get_port(), startup_timeout)?;
let mut runtime = Runtime::new()?;
let res = do_compile(
ProcessCommandCreator::new(&jobserver),
Expand Down
25 changes: 20 additions & 5 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ impl Default for DistConfig {
pub struct FileConfig {
pub cache: CacheConfigs,
pub dist: DistConfig,
pub server_startup_timeout_ms: Option<u64>,
}

// If the file doesn't exist or we can't read it, log the issue and proceed. If the
Expand Down Expand Up @@ -657,34 +658,43 @@ pub struct Config {
pub caches: Vec<CacheType>,
pub fallback_cache: DiskCacheConfig,
pub dist: DistConfig,
pub server_startup_timeout: Option<std::time::Duration>,
}

impl Config {
pub fn load() -> Result<Config> {
pub fn load() -> Result<Self> {
let env_conf = config_from_env()?;

let file_conf_path = config_file("SCCACHE_CONF", "config");
let file_conf = try_read_config_file(&file_conf_path)
.context("Failed to load config file")?
.unwrap_or_default();

Ok(Config::from_env_and_file_configs(env_conf, file_conf))
Ok(Self::from_env_and_file_configs(env_conf, file_conf))
}

fn from_env_and_file_configs(env_conf: EnvConfig, file_conf: FileConfig) -> Config {
fn from_env_and_file_configs(env_conf: EnvConfig, file_conf: FileConfig) -> Self {
let mut conf_caches: CacheConfigs = Default::default();

let FileConfig { cache, dist } = file_conf;
let FileConfig {
cache,
dist,
server_startup_timeout_ms,
} = file_conf;
conf_caches.merge(cache);

let server_startup_timeout =
server_startup_timeout_ms.map(std::time::Duration::from_millis);

let EnvConfig { cache } = env_conf;
conf_caches.merge(cache);

let (caches, fallback_cache) = conf_caches.into_vec_and_fallback();
Config {
Self {
caches,
fallback_cache,
dist,
server_startup_timeout,
}
}
}
Expand Down Expand Up @@ -926,6 +936,7 @@ fn config_overrides() {
..Default::default()
},
dist: Default::default(),
server_startup_timeout_ms: None,
};

assert_eq!(
Expand All @@ -947,6 +958,7 @@ fn config_overrides() {
size: 5,
},
dist: Default::default(),
server_startup_timeout: None,
}
);
}
Expand Down Expand Up @@ -1024,6 +1036,8 @@ fn test_gcs_oauth_url() {
#[test]
fn full_toml_parse() {
const CONFIG_STR: &str = r#"
server_startup_timeout_ms = 10000

[dist]
# where to find the scheduler
scheduler_url = "http://1.2.3.4:10600"
Expand Down Expand Up @@ -1131,6 +1145,7 @@ no_credentials = true
toolchain_cache_size: 5368709120,
rewrite_includes_only: false,
},
server_startup_timeout_ms: Some(10000),
}
)
}
1 change: 1 addition & 0 deletions tests/harness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ pub fn sccache_client_cfg(tmpdir: &Path) -> sccache::config::FileConfig {
toolchain_cache_size: TC_CACHE_SIZE,
rewrite_includes_only: false, // TODO
},
server_startup_timeout_ms: None,
}
}
#[cfg(feature = "dist-server")]
Expand Down
1 change: 1 addition & 0 deletions tests/oauth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ fn config_with_dist_auth(
toolchain_cache_size: 0,
rewrite_includes_only: true,
},
server_startup_timeout_ms: None,
}
}

Expand Down