diff --git a/docs/Configuration.md b/docs/Configuration.md index 953440dc1..50a68fe67 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -129,6 +129,7 @@ configuration variables * `SCCACHE_CONF` configuration file path * `SCCACHE_CACHED_CONF` * `SCCACHE_IDLE_TIMEOUT` how long the local daemon process waits for more client requests before exiting, in seconds. Set to `0` to run sccache permanently +* `SCCACHE_CONNECTION_TIMEOUT` how long clients should try to connect to the server before continuing, in seconds. * `SCCACHE_STARTUP_NOTIFY` specify a path to a socket which will be used for server completion notification * `SCCACHE_MAX_FRAME_LENGTH` how much data can be transferred between client and server * `SCCACHE_NO_DAEMON` set to `1` to disable putting the server to the background diff --git a/src/client.rs b/src/client.rs index 51a6a1fe3..f131a695f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -19,6 +19,18 @@ use byteorder::{BigEndian, ByteOrder}; use retry::{delay::Fixed, retry}; use std::io::{self, BufReader, BufWriter, Read}; use std::net::TcpStream; +use std::time::Duration; +use std::{env, net::ToSocketAddrs}; + +const DEFAULT_CONNECTION_TIMEOUT: u64 = 20; + +/// Get the time clients should try to connect to the server before continuing, in seconds. +pub(crate) fn get_connection_timeout() -> u64 { + env::var("SCCACHE_CONNECTION_TIMEOUT") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(DEFAULT_CONNECTION_TIMEOUT) +} /// A connection to an sccache server. pub struct ServerConnection { @@ -65,7 +77,10 @@ impl ServerConnection { /// Establish a TCP connection to an sccache server listening on `port`. pub fn connect_to_server(port: u16) -> io::Result { trace!("connect_to_server({})", port); - let stream = TcpStream::connect(("127.0.0.1", port))?; + let stream = TcpStream::connect_timeout( + &("127.0.0.1", port).to_socket_addrs()?.next().unwrap(), + Duration::from_secs(get_connection_timeout()), + )?; ServerConnection::new(stream) } diff --git a/src/dist/client_auth.rs b/src/dist/client_auth.rs index 5555411c0..2aa267c44 100644 --- a/src/dist/client_auth.rs +++ b/src/dist/client_auth.rs @@ -15,7 +15,7 @@ use tokio::runtime::Runtime; use url::Url; use uuid::Uuid; -use crate::errors::*; +use crate::{client::get_connection_timeout, errors::*}; // These (arbitrary) ports need to be registered as valid redirect urls in the oauth provider you're using pub const VALID_PORTS: &[u16] = &[12731, 32492, 56909]; @@ -503,7 +503,7 @@ async fn try_bind() -> Result { .expect("Expected at least one address in parsed socket address"); // Hyper binds with reuseaddr and reuseport so binding won't fail as you'd expect on Linux - match TcpStream::connect(addr) { + match TcpStream::connect_timeout(&addr, Duration::from_secs(get_connection_timeout())) { // Already open Ok(_) => continue, // Doesn't seem to be open