Skip to content

Commit

Permalink
Don't use flock on NFS mounts
Browse files Browse the repository at this point in the history
Completely skip file locking when we detect an NFS mount via `statfs`.

Closes #2615
  • Loading branch information
alexcrichton committed Apr 26, 2016
1 parent 191f65f commit b0ecb90
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 b0ecb90

Please sign in to comment.