From d19b41f2c6981dcdf5270e8f4582a95e51927e2a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 14 Mar 2019 08:17:38 -0700 Subject: [PATCH] Release a jobserver token while locking a file This is intended to fix #6747 where multiple Cargos invoked with the same jobserver would all have their own token but not actually run concurrently due to file locking. Instead the fix is that whenever Cargo blocks for a file lock with a configured global jobserver, a token is released just before we block and then reacquired afterwards. This way we should ensure that we're not hogging a cpu/token unnecessarily without doing any work! Closes #6747 --- Cargo.toml | 2 +- src/cargo/util/flock.rs | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2c5504421ec..708bed282b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ hex = "0.3" home = "0.3" ignore = "0.4" lazy_static = "1.2.0" -jobserver = "0.1.11" +jobserver = "0.1.13" lazycell = "1.2.0" libc = "0.2" log = "0.4.6" diff --git a/src/cargo/util/flock.rs b/src/cargo/util/flock.rs index bc87be6c9e6..e49a4daaa38 100644 --- a/src/cargo/util/flock.rs +++ b/src/cargo/util/flock.rs @@ -312,8 +312,27 @@ fn acquire( let msg = format!("waiting for file lock on {}", msg); config.shell().status_with_color("Blocking", &msg, Cyan)?; - block().chain_err(|| format!("failed to lock file: {}", path.display()))?; - return Ok(()); + // We're about to block the current process and not really do anything + // productive for what could possibly be a very long time. We could be + // waiting, for example, on another Cargo to finish a download, finish an + // entire build, etc. Since we're not doing anything productive we're not + // making good use of our jobserver token, if we have one. + // + // This can typically come about if `cargo` is invoked from `make` (or some + // other jobserver-providing system). In this situation it's actually best + // if we release the token back to the original jobserver to let some other + // cpu-hungry work continue to make progress. After we're done blocking + // we'll block waiting to reacquire a token as we'll probably be doing cpu + // hungry work ourselves. + let jobserver = config.jobserver_from_env(); + if let Some(server) = jobserver { + server.release_raw()?; + } + let result = block().chain_err(|| format!("failed to lock file: {}", path.display())); + if let Some(server) = jobserver { + server.acquire_raw()?; + } + return Ok(result?); #[cfg(all(target_os = "linux", not(target_env = "musl")))] fn is_on_nfs_mount(path: &Path) -> bool {