Skip to content

Commit

Permalink
Auto merge of #8093 - pfmooney:illumos-deps, r=alexcrichton
Browse files Browse the repository at this point in the history
Update dependencies to support illumos target

Several dependencies of cargo require updates in order to build with illumos as the `target_os` platform (rust-lang/rust#55553).  Most are patch revisions to include `#[cfg()]` updates.  In the case of `fs2`, the maintainer does not appear to be minding activity on the project, so it was forked into `fs3`, maintaining the same interfaces and logic (but featuring the widened platform support).
  • Loading branch information
bors committed Apr 13, 2020
2 parents 15d8044 + c04a87c commit 74e3a7d
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 27 deletions.
7 changes: 3 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ curl-sys = "0.4.22"
env_logger = "0.7.0"
pretty_env_logger = { version = "0.4", optional = true }
anyhow = "1.0"
filetime = "0.2"
filetime = "0.2.9"
flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] }
fs2 = "0.4"
git2 = "0.13.0"
git2 = "0.13.1"
git2-curl = "0.14.0"
glob = "0.3.0"
hex = "0.4"
Expand All @@ -45,7 +44,7 @@ jobserver = "0.1.21"
lazycell = "1.2.0"
libc = "0.2"
log = "0.4.6"
libgit2-sys = "0.12.0"
libgit2-sys = "0.12.1"
memchr = "2.1.3"
num_cpus = "1.0"
opener = "0.4"
Expand Down
154 changes: 131 additions & 23 deletions src/cargo/util/flock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ use std::io;
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::{Display, Path, PathBuf};

use fs2::{lock_contended_error, FileExt};
use termcolor::Color::Cyan;
#[cfg(windows)]
use winapi::shared::winerror::ERROR_INVALID_FUNCTION;

use crate::util::errors::{CargoResult, CargoResultExt};
use crate::util::paths;
use crate::util::Config;
use sys::*;

#[derive(Debug)]
pub struct FileLock {
Expand Down Expand Up @@ -95,7 +93,7 @@ impl Drop for FileLock {
fn drop(&mut self) {
if self.state != State::Unlocked {
if let Some(f) = self.f.take() {
let _ = f.unlock();
let _ = unlock(&f);
}
}
}
Expand Down Expand Up @@ -231,13 +229,13 @@ impl Filesystem {
.chain_err(|| format!("failed to open: {}", path.display()))?;
match state {
State::Exclusive => {
acquire(config, msg, &path, &|| f.try_lock_exclusive(), &|| {
f.lock_exclusive()
acquire(config, msg, &path, &|| try_lock_exclusive(&f), &|| {
lock_exclusive(&f)
})?;
}
State::Shared => {
acquire(config, msg, &path, &|| f.try_lock_shared(), &|| {
f.lock_shared()
acquire(config, msg, &path, &|| try_lock_shared(&f), &|| {
lock_shared(&f)
})?;
}
State::Unlocked => {}
Expand Down Expand Up @@ -281,8 +279,8 @@ fn acquire(
config: &Config,
msg: &str,
path: &Path,
r#try: &dyn Fn() -> io::Result<()>,
block: &dyn Fn() -> io::Result<()>,
lock_try: &dyn Fn() -> io::Result<()>,
lock_block: &dyn 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
Expand All @@ -298,24 +296,16 @@ fn acquire(
return Ok(());
}

match r#try() {
match lock_try() {
Ok(()) => return Ok(()),

// In addition to ignoring NFS which is commonly not working we also
// just ignore locking on filesystems that look like they don't
// implement file locking. We detect that here via the return value of
// locking (e.g., inspecting errno).
#[cfg(unix)]
Err(ref e) if e.raw_os_error() == Some(libc::ENOTSUP) => return Ok(()),

#[cfg(target_os = "linux")]
Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => return Ok(()),

#[cfg(windows)]
Err(ref e) if e.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32) => return Ok(()),
// implement file locking.
Err(e) if error_unsupported(&e) => return Ok(()),

Err(e) => {
if e.raw_os_error() != lock_contended_error().raw_os_error() {
if !error_contended(&e) {
let e = anyhow::Error::from(e);
let cx = format!("failed to lock file: {}", path.display());
return Err(e.context(cx).into());
Expand All @@ -325,7 +315,7 @@ 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()))?;
lock_block().chain_err(|| format!("failed to lock file: {}", path.display()))?;
return Ok(());

#[cfg(all(target_os = "linux", not(target_env = "musl")))]
Expand All @@ -352,3 +342,121 @@ fn acquire(
false
}
}

#[cfg(unix)]
mod sys {
use std::fs::File;
use std::io::{Error, Result};
use std::os::unix::io::AsRawFd;

pub(super) fn lock_shared(file: &File) -> Result<()> {
flock(file, libc::LOCK_SH)
}

pub(super) fn lock_exclusive(file: &File) -> Result<()> {
flock(file, libc::LOCK_EX)
}

pub(super) fn try_lock_shared(file: &File) -> Result<()> {
flock(file, libc::LOCK_SH | libc::LOCK_NB)
}

pub(super) fn try_lock_exclusive(file: &File) -> Result<()> {
flock(file, libc::LOCK_EX | libc::LOCK_NB)
}

pub(super) fn unlock(file: &File) -> Result<()> {
flock(file, libc::LOCK_UN)
}

pub(super) fn error_contended(err: &Error) -> bool {
err.raw_os_error().map_or(false, |x| x == libc::EWOULDBLOCK)
}

pub(super) fn error_unsupported(err: &Error) -> bool {
match err.raw_os_error() {
Some(libc::ENOTSUP) => true,
#[cfg(target_os = "linux")]
Some(libc::ENOSYS) => true,
_ => false,
}
}

#[cfg(not(target_os = "solaris"))]
fn flock(file: &File, flag: libc::c_int) -> Result<()> {
let ret = unsafe { libc::flock(file.as_raw_fd(), flag) };
if ret < 0 {
Err(Error::last_os_error())
} else {
Ok(())
}
}

#[cfg(target_os = "solaris")]
fn flock(file: &File, flag: libc::c_int) -> Result<()> {
// Solaris lacks flock(), so simply succeed with a no-op
Ok(())
}
}

#[cfg(windows)]
mod sys {
use std::fs::File;
use std::io::{Error, Result};
use std::mem;
use std::os::windows::io::AsRawHandle;

use winapi::shared::minwindef::DWORD;
use winapi::shared::winerror::{ERROR_INVALID_FUNCTION, ERROR_LOCK_VIOLATION};
use winapi::um::fileapi::{LockFileEx, UnlockFile};
use winapi::um::minwinbase::{LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY};

pub(super) fn lock_shared(file: &File) -> Result<()> {
lock_file(file, 0)
}

pub(super) fn lock_exclusive(file: &File) -> Result<()> {
lock_file(file, LOCKFILE_EXCLUSIVE_LOCK)
}

pub(super) fn try_lock_shared(file: &File) -> Result<()> {
lock_file(file, LOCKFILE_FAIL_IMMEDIATELY)
}

pub(super) fn try_lock_exclusive(file: &File) -> Result<()> {
lock_file(file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY)
}

pub(super) fn error_contended(err: &Error) -> bool {
err.raw_os_error()
.map_or(false, |x| x == ERROR_LOCK_VIOLATION as i32)
}

pub(super) fn error_unsupported(err: &Error) -> bool {
err.raw_os_error()
.map_or(false, |x| x == ERROR_INVALID_FUNCTION as i32)
}

pub(super) fn unlock(file: &File) -> Result<()> {
unsafe {
let ret = UnlockFile(file.as_raw_handle(), 0, 0, !0, !0);
if ret == 0 {
Err(Error::last_os_error())
} else {
Ok(())
}
}
}

fn lock_file(file: &File, flags: DWORD) -> Result<()> {
unsafe {
let mut overlapped = mem::zeroed();
let ret = LockFileEx(file.as_raw_handle(), flags, 0, !0, !0, &mut overlapped);
if ret == 0 {
Err(Error::last_os_error())
} else {
Ok(())
}
}
}
}

0 comments on commit 74e3a7d

Please sign in to comment.