Skip to content

Commit

Permalink
Auto merge of #2623 - alexcrichton:nfs-lol-no, r=brson
Browse files Browse the repository at this point in the history
Don't use flock on NFS mounts

Completely skip file locking when we detect an NFS mount via `statfs`.

Closes #2615
  • Loading branch information
bors committed Apr 29, 2016
2 parents afac7fc + b0ecb90 commit 27161ec
Showing 1 changed file with 42 additions and 2 deletions.
44 changes: 42 additions & 2 deletions src/cargo/util/flock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,21 @@ fn acquire(config: &Config,
path: &Path,
try: &Fn() -> io::Result<()>,
block: &Fn() -> io::Result<()>) -> CargoResult<()> {

// File locking on Unix is currently implemented via `flock`, which is known
// to be broken on NFS. We could in theory just ignore errors that happen on
// NFS, but apparently the failure mode [1] for `flock` on NFS is **blocking
// forever**, even if the nonblocking flag is passed!
//
// As a result, we just skip all file locks entirely on NFS mounts. That
// should avoid calling any `flock` functions at all, and it wouldn't work
// there anyway.
//
// [1]: https://github.com/rust-lang/cargo/issues/2615
if is_on_nfs_mount(path) {
return Ok(())
}

match try() {
Ok(()) => return Ok(()),
Err(e) => {
Expand All @@ -263,9 +278,34 @@ fn acquire(config: &Config,
let msg = format!("waiting for file lock on {}", msg);
try!(config.shell().err().say_status("Blocking", &msg, CYAN, true));

block().chain_error(|| {
return block().chain_error(|| {
human(format!("failed to lock file: {}", path.display()))
})
});

#[cfg(target_os = "linux")]
fn is_on_nfs_mount(path: &Path) -> bool {
use std::ffi::CString;
use std::mem;
use std::os::unix::prelude::*;
use libc;

let path = match CString::new(path.as_os_str().as_bytes()) {
Ok(path) => path,
Err(_) => return false,
};

unsafe {
let mut buf: libc::statfs = mem::zeroed();
let r = libc::statfs(path.as_ptr(), &mut buf);

r == 0 && buf.f_type == libc::NFS_SUPER_MAGIC
}
}

#[cfg(not(target_os = "linux"))]
fn is_on_nfs_mount(_path: &Path) -> bool {
false
}
}

fn create_dir_all(path: &Path) -> io::Result<()> {
Expand Down

0 comments on commit 27161ec

Please sign in to comment.