diff options
Diffstat (limited to 'src/runner')
-rw-r--r-- | src/runner/runc.rs | 88 | ||||
-rw-r--r-- | src/runner/runc/init.rs | 47 | ||||
-rw-r--r-- | src/runner/runc/run.rs | 18 |
3 files changed, 142 insertions, 11 deletions
diff --git a/src/runner/runc.rs b/src/runner/runc.rs index b323d5d..663dc7a 100644 --- a/src/runner/runc.rs +++ b/src/runner/runc.rs @@ -1,21 +1,87 @@ -use super::*; -use crate::types::TaskMap; +mod init; +mod run; -pub struct RuncRunner<'a> { - tasks: &'a TaskMap, +use std::{io, process}; + +use ipc_channel::ipc; +use nix::unistd; +use serde::{Deserialize, Serialize}; + +use crate::types::*; +use crate::unshare; +use crate::util::CheckDisconnect; + +#[derive(Debug, Deserialize, Serialize)] +struct Request(TaskRef, Task, ipc::IpcSender<run::Error>); + +fn runner(init_error_sender: ipc::IpcSender<init::Error>, channel: ipc::IpcReceiver<Request>) -> ! { + if let Err(error) = init::runc_initialize() { + init_error_sender.send(error).expect("IPC send() failed"); + process::exit(1); + } + + drop(init_error_sender); + + while let Ok(request) = channel.recv() { + let Request(task, task_def, reply_sender) = request; + if let Err(error) = run::handle_task(task, task_def) { + reply_sender.send(error).expect("IPC send() failed"); + } + } + + process::exit(0); +} + +pub struct RuncRunner { + channel: ipc::IpcSender<Request>, } -impl<'a> RuncRunner<'a> { - pub fn new(tasks: &'a TaskMap) -> Self { - RuncRunner { tasks } +impl RuncRunner { + /// Creates a new Runc runner + /// + /// Unsafe: Do not call in multithreaded processes + pub unsafe fn new() -> io::Result<Self> { + let (tx, rx) = ipc::channel().expect("IPC channel creation failed"); + let (init_error_tx, init_error_rx) = ipc::channel().expect("IPC channel creation failed"); + + let pid = match unistd::fork().expect("fork()") { + unistd::ForkResult::Parent { child } => { + drop(rx); + drop(init_error_tx); + child + } + unistd::ForkResult::Child => { + drop(tx); + drop(init_error_rx); + runner(init_error_tx, rx); + /* Not reached */ + } + }; + + init_error_rx + .recv() + .check_disconnect() + .expect("IPC recv() error")?; + + unshare::idmap(pid)?; + + Ok(RuncRunner { channel: tx }) } } -impl<'a> Runner for RuncRunner<'a> { - fn run(&self, task: &TaskRef) -> Result<()> { - let task_def = self.tasks.get(task).expect("Invalid TaskRef"); +impl super::Runner for RuncRunner { + fn run(&self, tasks: &TaskMap, task: &TaskRef) -> super::Result<()> { + let task_def = tasks.get(task).expect("Invalid TaskRef"); + let (reply_tx, reply_rx) = ipc::channel().expect("IPC channel creation failed"); + + self.channel + .send(Request(task.clone(), task_def.clone(), reply_tx)) + .expect("RuncRunner task submission failed"); - println!("{}:\n\t{:?}", task, task_def); + reply_rx + .recv() + .check_disconnect() + .expect("IPC recv() error")?; Ok(()) } diff --git a/src/runner/runc/init.rs b/src/runner/runc/init.rs new file mode 100644 index 0000000..02b89e4 --- /dev/null +++ b/src/runner/runc/init.rs @@ -0,0 +1,47 @@ +use std::io; + +use nix::{ + mount::{self, MsFlags}, + sched::{self, CloneFlags}, +}; +use serde::{Deserialize, Serialize}; + +fn mount_buildtmp() -> nix::Result<()> { + mount::mount::<_, _, _, str>( + Some("buildtmp"), + "build/tmp", + Some("tmpfs"), + MsFlags::empty(), + None, + ) +} + +#[derive(Debug, Deserialize, Serialize)] +pub enum Error { + Code(i32), + String(String), +} + +impl From<nix::Error> for Error { + fn from(error: nix::Error) -> Self { + match error { + nix::Error::Sys(code) => Error::Code(code as i32), + _ => Error::String(error.to_string()), + } + } +} + +impl From<Error> for io::Error { + fn from(error: Error) -> Self { + match error { + Error::Code(code) => io::Error::from_raw_os_error(code), + Error::String(string) => io::Error::new(io::ErrorKind::Other, string), + } + } +} + +pub fn runc_initialize() -> Result<(), Error> { + sched::unshare(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWNS)?; + mount_buildtmp()?; + Ok(()) +} diff --git a/src/runner/runc/run.rs b/src/runner/runc/run.rs new file mode 100644 index 0000000..2d13330 --- /dev/null +++ b/src/runner/runc/run.rs @@ -0,0 +1,18 @@ +use std::io; + +use serde::{Deserialize, Serialize}; + +use crate::types::*; +#[derive(Debug, Deserialize, Serialize)] +pub struct Error; + +impl From<Error> for io::Error { + fn from(_: Error) -> Self { + io::Error::new(io::ErrorKind::Other, "Failed to run task") + } +} + +pub fn handle_task(task: TaskRef, task_def: Task) -> Result<(), Error> { + println!("{}:\n\t{:?}", task, task_def); + Ok(()) +} |