diff --git a/Cargo.lock b/Cargo.lock index 9da3f79141d..30ff38707f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,7 @@ dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "rls-analysis 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 23483a866df..6f833fb0909 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,9 @@ build = "build.rs" [dependencies] cargo = { git = "https://github.com/rust-lang/cargo" } env_logger = "0.4" +jsonrpc-core = "7.0.1" languageserver-types = "0.12" +lazy_static = "0.2" log = "0.3" racer = "2.0.6" rls-analysis = "0.4.5" @@ -26,4 +28,3 @@ serde_derive = "1.0" toml = "0.4" url = "1.1.0" url_serde = "0.2.0" -jsonrpc-core = "7.0.1" diff --git a/src/build/mod.rs b/src/build/mod.rs index 6d6f2f3e83c..93cdfba541c 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -19,11 +19,12 @@ use std::ffi::OsString; use std::io::{self, Write}; use std::mem; use std::path::{Path, PathBuf}; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::atomic::{AtomicBool, Ordering}; use std::thread; use std::time::Duration; + mod cargo; mod rustc; @@ -409,15 +410,24 @@ impl Write for BufWriter { } } + +// Ensures we don't race on the env vars. This is only likely in tests, where we +// have multiple copies of the RLS running in the same process. +lazy_static! { + static ref ENV_LOCK: Mutex<()> = Mutex::new(()); +} + // An RAII helper to set and reset the current working directory and env vars. -struct Environment { +struct Environment<'a> { old_vars: HashMap>, + _guard: MutexGuard<'a, ()>, } -impl Environment { - fn push(envs: &HashMap>) -> Environment { +impl<'a> Environment<'a> { + fn push(envs: &HashMap>) -> Environment<'a> { let mut result = Environment { old_vars: HashMap::new(), + _guard: ENV_LOCK.lock().unwrap(), }; for (k, v) in envs { @@ -435,7 +445,7 @@ impl Environment { } } -impl Drop for Environment { +impl<'a> Drop for Environment<'a> { fn drop(&mut self) { for (k, v) in &self.old_vars { match *v { diff --git a/src/build/rustc.rs b/src/build/rustc.rs index 967cc0df212..ae903a1fd53 100644 --- a/src/build/rustc.rs +++ b/src/build/rustc.rs @@ -36,6 +36,7 @@ use std::io; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; + // Runs a single instance of rustc. Runs in-process. pub fn rustc(vfs: &Vfs, args: &[String], envs: &HashMap>, build_dir: &Path, rls_config: Arc>) -> BuildResult { trace!("rustc - args: `{:?}`, envs: {:?}, build dir: {:?}", args, envs, build_dir); @@ -47,6 +48,7 @@ pub fn rustc(vfs: &Vfs, args: &[String], envs: &HashMap if rls_config.lock().unwrap().clear_env_rust_log { local_envs.insert(String::from("RUST_LOG"), None); } + let _restore_env = Environment::push(&local_envs); let buf = Arc::new(Mutex::new(vec![])); let err_buf = buf.clone(); diff --git a/src/main.rs b/src/main.rs index 9a45a9717b4..e6fe37a6cf8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,8 @@ extern crate cargo; extern crate env_logger; extern crate languageserver_types as ls_types; #[macro_use] +extern crate lazy_static; +#[macro_use] extern crate log; extern crate racer; extern crate rls_analysis as analysis; diff --git a/src/test/harness.rs b/src/test/harness.rs index d23c4d3538c..b5de6f64b65 100644 --- a/src/test/harness.rs +++ b/src/test/harness.rs @@ -25,7 +25,7 @@ use serde_json; use server::{self as ls_server, ServerMessage}; use vfs; -const TEST_TIMEOUT_IN_SEC: u64 = 60; +const TEST_TIMEOUT_IN_SEC: u64 = 240; // Initialise and run the internals of an LS protocol RLS server. pub fn mock_server(messages: Vec) -> (ls_server::LsService, LsResultList)