Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Don't use flock on NFS mounts #2623

Merged
merged 1 commit into from
Apr 29, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 42 additions & 2 deletions src/cargo/util/flock.rs
Original file line number Diff line number Diff line change
@@ -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) => {
@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After googling this I'm even more curious. Just magic stuff.

}
}

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

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