diff options
Diffstat (limited to 'src/runner/runc.rs')
-rw-r--r-- | src/runner/runc.rs | 88 |
1 files changed, 77 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(()) } |