summaryrefslogtreecommitdiffstats
path: root/crates/runner/src
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2021-10-25 22:59:48 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2021-10-25 22:59:48 +0200
commitef2e197f1343d3c99b1896b7461e291baad8988e (patch)
tree4a633599f42a0c3594e99b9fbcd31e547100e5d0 /crates/runner/src
parente97a431920bdbe00a4ecef2c3b68639a68525bed (diff)
downloadrebel-ef2e197f1343d3c99b1896b7461e291baad8988e.tar
rebel-ef2e197f1343d3c99b1896b7461e291baad8988e.zip
Add lockfile for build state directory
Use flock() to ensure that there are no concurrent instances using the same build state. More fine-gained locking may be implemented in the future.
Diffstat (limited to 'crates/runner/src')
-rw-r--r--crates/runner/src/lib.rs23
-rw-r--r--crates/runner/src/paths.rs2
2 files changed, 21 insertions, 4 deletions
diff --git a/crates/runner/src/lib.rs b/crates/runner/src/lib.rs
index 658a833..45366f3 100644
--- a/crates/runner/src/lib.rs
+++ b/crates/runner/src/lib.rs
@@ -6,9 +6,12 @@ mod tar;
mod task;
mod util;
+use std::{fs::File, os::unix::prelude::AsRawFd, path::Path};
+
use capctl::prctl;
use ipc_channel::ipc;
use nix::{
+ fcntl,
sched::CloneFlags,
sys::{signal, stat, wait},
unistd::{self, Gid, Uid},
@@ -16,6 +19,7 @@ use nix::{
use serde::{Deserialize, Serialize};
use common::{error::*, types::*};
+use util::fs;
use self::{
jobserver::Jobserver,
@@ -72,7 +76,7 @@ fn runner_loop(mut channel: ipc::IpcReceiver<Message>) {
}
}
-fn runner(uid: Uid, gid: Gid, channel: ipc::IpcReceiver<Message>) {
+fn runner(uid: Uid, gid: Gid, channel: ipc::IpcReceiver<Message>, _lockfile: File) {
ns::mount_proc();
ns::setup_userns(Uid::from_raw(0), Gid::from_raw(0), uid, gid);
@@ -106,6 +110,8 @@ impl Runner {
///
/// Unsafe: Do not call in multithreaded processes
pub unsafe fn new() -> Result<Self> {
+ let lockfile = Runner::lock()?;
+
let uid = unistd::geteuid();
let gid = unistd::getegid();
@@ -116,7 +122,7 @@ impl Runner {
(tx, rx),
|(tx, rx)| {
drop(tx);
- runner(uid, gid, rx);
+ runner(uid, gid, rx, lockfile);
},
)
.expect("clone()")
@@ -124,9 +130,18 @@ impl Runner {
Ok(Runner { channel: tx })
}
-}
-impl Runner {
+ fn lock() -> Result<File> {
+ 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<Result<TaskOutput>> {
let (reply_tx, reply_rx) = ipc::channel().expect("IPC channel creation failed");
diff --git a/crates/runner/src/paths.rs b/crates/runner/src/paths.rs
index 632f030..9539782 100644
--- a/crates/runner/src/paths.rs
+++ b/crates/runner/src/paths.rs
@@ -8,6 +8,7 @@
//! ├── downloads/
//! │   └── ...
//! ├── state/
+//! │ ├── build.lock
//! │   ├── output/
//! │   │  ├── <input hash>.tar.tmp # during packing
//! │   │  ├── <archive hash>.tar # files are renamed when packing is finished
@@ -49,6 +50,7 @@ pub const TASK_TMP_DIR: &str = "build/tmp/task";
pub const TASK_TMP_ROOTFS_SUBDIR: &str = "rootfs";
pub const TASK_TMP_DEPENDS_SUBDIR: &str = "depends";
+pub const LOCKFILE: &str = "build/state/build.lock";
pub const OUTPUT_STATE_DIR: &str = "build/state/output";
pub const TASK_STATE_DIR: &str = "build/state/task";
pub const LAYER_STATE_DIR: &str = "build/state/layer";