summaryrefslogtreecommitdiffstats
path: root/src/runner/runc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/runner/runc.rs')
-rw-r--r--src/runner/runc.rs88
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(())
}