From 61746b64b0e7087b17b21df6a1c7291ad25cd428 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 26 Oct 2021 17:03:07 +0200 Subject: runner: make lock() function more generic --- crates/runner/src/lib.rs | 18 +++--------------- crates/runner/src/util/unix.rs | 25 ++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 16 deletions(-) (limited to 'crates/runner/src') diff --git a/crates/runner/src/lib.rs b/crates/runner/src/lib.rs index af1e2a7..d0d8317 100644 --- a/crates/runner/src/lib.rs +++ b/crates/runner/src/lib.rs @@ -6,12 +6,11 @@ mod tar; mod task; mod util; -use std::{fs::File, os::unix::prelude::AsRawFd, path::Path}; +use std::fs::File; use capctl::prctl; use ipc_channel::ipc; use nix::{ - fcntl, sched::CloneFlags, sys::{signal, stat, wait}, unistd::{self, Gid, Uid}, @@ -19,7 +18,6 @@ use nix::{ use serde::{Deserialize, Serialize}; use common::{error::*, types::*}; -use util::fs; use self::{ jobserver::Jobserver, @@ -123,7 +121,8 @@ impl Runner { /// /// Unsafe: Do not call in multithreaded processes pub unsafe fn new(options: &Options) -> Result { - let lockfile = Runner::lock()?; + let lockfile = unix::lock(paths::LOCKFILE, true, false) + .context("Failed to get lock on build directory, is another instance running?")?; let uid = unistd::geteuid(); let gid = unistd::getegid(); @@ -144,17 +143,6 @@ impl Runner { Ok(Runner { channel: tx }) } - fn lock() -> Result { - let path = Path::new(paths::LOCKFILE); - fs::mkdir(path.parent().unwrap())?; - let file = fs::create(path)?; - - fcntl::flock(file.as_raw_fd(), fcntl::FlockArg::LockExclusiveNonblock) - .context("Failed to get lock on build directory, is another instance running?")?; - - Ok(file) - } - pub fn spawn(&self, task: &Task) -> ipc::IpcReceiver> { let (reply_tx, reply_rx) = ipc::channel().expect("IPC channel creation failed"); diff --git a/crates/runner/src/util/unix.rs b/crates/runner/src/util/unix.rs index 48db764..710138c 100644 --- a/crates/runner/src/util/unix.rs +++ b/crates/runner/src/util/unix.rs @@ -1,4 +1,4 @@ -use std::os::unix::prelude::*; +use std::{fs::File, os::unix::prelude::*, path::Path}; use nix::{ fcntl::{self, FcntlArg, FdFlag, OFlag}, @@ -8,6 +8,8 @@ use nix::{ use common::error::*; +use super::fs; + pub fn set_blocking(fd: RawFd, blocking: bool) -> Result<()> { let flags = unsafe { OFlag::from_bits_unchecked(fcntl::fcntl(fd, FcntlArg::F_GETFL).context("fcntl(F_GETFL)")?) @@ -59,3 +61,24 @@ pub fn nproc() -> Result { Ok(count) } + +pub fn lock>(path: P, exclusive: bool, blocking: bool) -> Result { + use fcntl::FlockArg::*; + + if let Some(parent) = path.as_ref().parent() { + fs::mkdir(parent)?; + } + + let arg = match (exclusive, blocking) { + (true, true) => LockExclusive, + (true, false) => LockExclusiveNonblock, + (false, true) => LockShared, + (false, false) => LockSharedNonblock, + }; + + let file = fs::create(path.as_ref())?; + fcntl::flock(file.as_raw_fd(), arg) + .with_context(|| format!("flock failed on {:?}", path.as_ref()))?; + + Ok(file) +} -- cgit v1.2.3