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
This commit is contained in:
Alex Crichton 2019-03-14 08:17:38 -07:00
parent 9eeece1db5
commit d19b41f2c6
2 changed files with 22 additions and 3 deletions

View file

@ -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"

View file

@ -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 {