Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feature: Impl Client::{supports_try_acquire, try_acquire} #73

Merged
merged 3 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
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
36 changes: 36 additions & 0 deletions .github/actions/compile-make/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Compile make
description: compile-make
inputs:
version:
description: make version
required: true
workaround:
description: enable workaround for _alloc bug
required: false
default: "false"

runs:
using: composite
steps:
- name: Cache make compiled
if: ${{ !startsWith(runner.os, 'windows') }}
id: cache-maka
uses: actions/cache@v4
with:
path: /usr/local/bin/make-${{ inputs.version }}
key: v1-${{ runner.os }}-make-${{ inputs.version }}

- name: Make GNU Make from source
if: ${{ !startsWith(runner.os, 'windows') && steps.cache-make.outputs.cache-hit != 'true' }}
env:
VERSION: ${{ inputs.version }}
WORKAROUND: ${{ inputs.workaround }}
shell: bash
run: |
curl "https://ftp.gnu.org/gnu/make/make-${VERSION}.tar.gz" | tar xz
pushd "make-${VERSION}"
./configure
[[ "$WORKAROUND" = "true" ]] && sed -i 's/#if !defined __alloca \&\& !defined __GNU_LIBRARY__/#if !defined __alloca \&\& defined __GNU_LIBRARY__/g; s/#ifndef __GNU_LIBRARY__/#ifdef __GNU_LIBRARY__/g' "./glob/glob.c"
make -j 4
popd
cp -p "make-${VERSION}/make" "/usr/local/bin/make-${VERSION}"
75 changes: 29 additions & 46 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,54 +13,37 @@ jobs:
rust: [stable, beta, nightly]
os: [ubuntu-latest, macos-14, windows-latest]
steps:
- uses: actions/checkout@master
- name: Install Rust (rustup)
run: |
rustup toolchain install ${{ matrix.rust }} --no-self-update --profile minimal
rustup default ${{ matrix.rust }}
shell: bash

- uses: Swatinem/rust-cache@v2
- uses: actions/checkout@master
- name: Install Rust (rustup)
run: |
rustup toolchain install ${{ matrix.rust }} --no-self-update --profile minimal
rustup default ${{ matrix.rust }}
shell: bash

- run: cargo test --locked
- uses: Swatinem/rust-cache@v2

- name: Cache make compiled
if: ${{ !startsWith(matrix.os, 'windows') }}
id: cache-make
uses: actions/cache@v4
with:
path: /usr/local/bin/make
key: ${{ runner.os }}-make-4.4.1
- run: cargo test --locked

# Compile it from source (temporarily)
- name: Make GNU Make from source
if: ${{ !startsWith(matrix.os, 'windows') && steps.cache-make.outputs.cache-hit != 'true' }}
env:
VERSION: "4.4.1"
shell: bash
run: |
curl "https://ftp.gnu.org/gnu/make/make-${VERSION}.tar.gz" | tar xz
pushd "make-${VERSION}"
./configure
make -j 4
popd
cp -p "make-${VERSION}/make" /usr/local/bin
- name: Compile make 4.4.1
uses: ./.github/actions/compile-make
with:
version: 4.4.1

- name: Test against GNU Make from source
if: ${{ !startsWith(matrix.os, 'windows') }}
shell: bash
run: cargo test --locked
env:
MAKE: /usr/local/bin/make
- name: Test against GNU Make 4.4.1
if: ${{ !startsWith(matrix.os, 'windows') }}
shell: bash
run: cargo test --locked
env:
MAKE: /usr/local/bin/make-4.4.1

rustfmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Install Rust
run: rustup update stable && rustup default stable && rustup component add rustfmt
- run: cargo fmt -- --check
- uses: actions/checkout@master
- name: Install Rust
run: rustup update stable && rustup default stable && rustup component add rustfmt
- run: cargo fmt -- --check

publish_docs:
name: Publish Documentation
Expand All @@ -86,12 +69,12 @@ jobs:
matrix:
os: [ubuntu-latest, macos-14, windows-latest]
steps:
- uses: actions/checkout@master
- name: Install Rust (rustup)
run: rustup toolchain install nightly --no-self-update --profile minimal
shell: bash
- uses: actions/checkout@master
- name: Install Rust (rustup)
run: rustup toolchain install nightly --no-self-update --profile minimal
shell: bash

- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2

- run: cargo hack check --lib --rust-version --ignore-private --locked
- run: cargo hack check --lib --rust-version --ignore-private --locked
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
target/
**/*.rs.bk
Cargo.lock
23 changes: 21 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ edition = "2021"
rust-version = "1.63"

[target.'cfg(unix)'.dependencies]
libc = "0.2.72"
libc = "0.2.87"

[target.'cfg(unix)'.dev-dependencies]
nix = { version = "0.28.0", features = ["fs"] }

[dev-dependencies]
tempfile = "3.10.1"
Expand Down
142 changes: 96 additions & 46 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,32 @@ impl Client {
})
}

/// Acquires a token from this jobserver client in a non-blocking way.
///
/// # Return value
///
/// On successful acquisition of a token an instance of [`Acquired`] is
/// returned. This structure, when dropped, will release the token back to
/// the jobserver. It's recommended to avoid leaking this value.
///
/// # Errors
///
/// If an I/O error happens while acquiring a token then this function will
/// return immediately with the error. If an error is returned then a token
/// was not acquired.
///
/// If non-blocking acquire is not supported, the return error will have its `kind()`
/// set to [`io::ErrorKind::Unsupported`].
pub fn try_acquire(&self) -> io::Result<Option<Acquired>> {
let ret = self.inner.try_acquire()?;

Ok(ret.map(|data| Acquired {
client: self.inner.clone(),
data,
disabled: false,
}))
}

/// Returns amount of tokens in the read-side pipe.
///
/// # Return value
Expand Down Expand Up @@ -607,52 +633,76 @@ fn find_jobserver_auth(var: &str) -> Option<&str> {
.and_then(|s| s.split(' ').next())
}

#[test]
fn no_helper_deadlock() {
let x = crate::Client::new(32).unwrap();
let _y = x.clone();
std::mem::drop(x.into_helper_thread(|_| {}).unwrap());
}
#[cfg(test)]
mod test {
use super::*;

pub(super) fn run_named_fifo_try_acquire_tests(client: &Client) {
assert!(client.try_acquire().unwrap().is_none());
client.release_raw().unwrap();

#[test]
fn test_find_jobserver_auth() {
let cases = [
("", None),
("-j2", None),
("-j2 --jobserver-auth=3,4", Some("3,4")),
("--jobserver-auth=3,4 -j2", Some("3,4")),
("--jobserver-auth=3,4", Some("3,4")),
("--jobserver-auth=fifo:/myfifo", Some("fifo:/myfifo")),
("--jobserver-auth=", Some("")),
("--jobserver-auth", None),
("--jobserver-fds=3,4", Some("3,4")),
("--jobserver-fds=fifo:/myfifo", Some("fifo:/myfifo")),
("--jobserver-fds=", Some("")),
("--jobserver-fds", None),
(
"--jobserver-auth=auth-a --jobserver-auth=auth-b",
Some("auth-b"),
),
(
"--jobserver-auth=auth-b --jobserver-auth=auth-a",
Some("auth-a"),
),
("--jobserver-fds=fds-a --jobserver-fds=fds-b", Some("fds-b")),
("--jobserver-fds=fds-b --jobserver-fds=fds-a", Some("fds-a")),
(
"--jobserver-auth=auth-a --jobserver-fds=fds-a --jobserver-auth=auth-b",
Some("auth-b"),
),
(
"--jobserver-fds=fds-a --jobserver-auth=auth-a --jobserver-fds=fds-b",
Some("auth-a"),
),
];
for (var, expected) in cases {
let actual = find_jobserver_auth(var);
assert_eq!(
actual, expected,
"expect {expected:?}, got {actual:?}, input `{var:?}`"
);
let acquired = client.try_acquire().unwrap().unwrap();
assert!(client.try_acquire().unwrap().is_none());

drop(acquired);
client.try_acquire().unwrap().unwrap();
}

#[cfg(not(unix))]
#[test]
fn test_try_acquire() {
let client = Client::new(0).unwrap();

run_named_fifo_try_acquire_tests(&client);
}

#[test]
fn no_helper_deadlock() {
let x = crate::Client::new(32).unwrap();
let _y = x.clone();
std::mem::drop(x.into_helper_thread(|_| {}).unwrap());
}

#[test]
fn test_find_jobserver_auth() {
let cases = [
("", None),
("-j2", None),
("-j2 --jobserver-auth=3,4", Some("3,4")),
("--jobserver-auth=3,4 -j2", Some("3,4")),
("--jobserver-auth=3,4", Some("3,4")),
("--jobserver-auth=fifo:/myfifo", Some("fifo:/myfifo")),
("--jobserver-auth=", Some("")),
("--jobserver-auth", None),
("--jobserver-fds=3,4", Some("3,4")),
("--jobserver-fds=fifo:/myfifo", Some("fifo:/myfifo")),
("--jobserver-fds=", Some("")),
("--jobserver-fds", None),
(
"--jobserver-auth=auth-a --jobserver-auth=auth-b",
Some("auth-b"),
),
(
"--jobserver-auth=auth-b --jobserver-auth=auth-a",
Some("auth-a"),
),
("--jobserver-fds=fds-a --jobserver-fds=fds-b", Some("fds-b")),
("--jobserver-fds=fds-b --jobserver-fds=fds-a", Some("fds-a")),
(
"--jobserver-auth=auth-a --jobserver-fds=fds-a --jobserver-auth=auth-b",
Some("auth-b"),
),
(
"--jobserver-fds=fds-a --jobserver-auth=auth-a --jobserver-fds=fds-b",
Some("auth-a"),
),
];
for (var, expected) in cases {
let actual = find_jobserver_auth(var);
assert_eq!(
actual, expected,
"expect {expected:?}, got {actual:?}, input `{var:?}`"
);
}
}
}
Loading