diff options
Diffstat (limited to 'crates/runner/src/lib.rs')
-rw-r--r-- | crates/runner/src/lib.rs | 23 |
1 files changed, 19 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"); |