marked created fds as to keep
This commit is contained in:
parent
1486fc7418
commit
ff32b48633
@ -1,5 +1,6 @@
|
||||
use super::{Spawner, TriggerData};
|
||||
use crate::specification::{Arg, FileSocket, Pipe};
|
||||
use crate::void::VoidBuilder;
|
||||
use crate::{Error, Result};
|
||||
|
||||
use std::ffi::CString;
|
||||
@ -7,36 +8,42 @@ use std::fs::File;
|
||||
use std::net::TcpListener;
|
||||
use std::os::unix::io::IntoRawFd;
|
||||
|
||||
/**
|
||||
* perform initial processing with ambient authority
|
||||
* for things like network sockets.
|
||||
*/
|
||||
pub struct PreparedArgs(Vec<PreparedArg>);
|
||||
|
||||
impl PreparedArgs {
|
||||
pub fn prepare_ambient(args: &[Arg]) -> Result<Self> {
|
||||
/**
|
||||
* perform initial processing with ambient authority
|
||||
* for things like network sockets. update the builder
|
||||
* with newly passed fds. the mutable call is allowed
|
||||
* to use up things such as pipes and sockets.
|
||||
*/
|
||||
pub fn prepare_ambient_mut(
|
||||
spawner: &mut Spawner,
|
||||
builder: &mut VoidBuilder,
|
||||
args: &[Arg],
|
||||
) -> Result<Self> {
|
||||
let mut v = Vec::with_capacity(args.len());
|
||||
|
||||
for arg in args {
|
||||
v.push(PreparedArg::prepare_ambient(arg)?);
|
||||
v.push(PreparedArg::prepare_ambient_mut(spawner, builder, arg)?);
|
||||
}
|
||||
|
||||
Ok(PreparedArgs(v))
|
||||
}
|
||||
|
||||
pub(super) fn prepare_void_mut(
|
||||
self,
|
||||
spawner: &mut Spawner,
|
||||
entrypoint: &str,
|
||||
trigger: &mut TriggerData,
|
||||
) -> Result<Vec<CString>> {
|
||||
let mut v = Vec::new();
|
||||
/**
|
||||
* perform initial processing with ambient authority
|
||||
* for things like network sockets. update the builder
|
||||
* with newly passed fds.
|
||||
*/
|
||||
pub fn prepare_ambient(builder: &mut VoidBuilder, args: &[Arg]) -> Result<Self> {
|
||||
let mut v = Vec::with_capacity(args.len());
|
||||
|
||||
for arg in self.0 {
|
||||
v.extend(arg.prepare_void_mut(spawner, entrypoint, trigger)?)
|
||||
for arg in args {
|
||||
v.push(PreparedArg::prepare_ambient(builder, arg)?);
|
||||
}
|
||||
|
||||
Ok(v)
|
||||
Ok(PreparedArgs(v))
|
||||
}
|
||||
|
||||
pub(super) fn prepare_void(
|
||||
@ -65,10 +72,10 @@ enum PreparedArg {
|
||||
File(File),
|
||||
|
||||
/// A chosen end of a named pipe
|
||||
Pipe(Pipe),
|
||||
Pipe(File),
|
||||
|
||||
/// File socket
|
||||
FileSocket(FileSocket),
|
||||
FileSocket(File),
|
||||
|
||||
/// A value specified by the trigger
|
||||
/// NOTE: Only valid if the trigger is of type Pipe(...) or FileSocket(...)
|
||||
@ -89,57 +96,60 @@ impl PreparedArg {
|
||||
* Leave the remainder untouched so they can be processed in parallel
|
||||
* (in the child process) and to reduce authority
|
||||
*/
|
||||
fn prepare_ambient(arg: &Arg) -> Result<Self> {
|
||||
fn prepare_ambient_mut(
|
||||
spawner: &mut Spawner,
|
||||
builder: &mut VoidBuilder,
|
||||
arg: &Arg,
|
||||
) -> Result<Self> {
|
||||
Ok(match arg {
|
||||
Arg::File(path) => PreparedArg::File(File::open(path)?),
|
||||
Arg::Pipe(p) => {
|
||||
let pipe = match p {
|
||||
Pipe::Rx(s) => spawner.pipes.get_mut(s).unwrap().take_read(),
|
||||
Pipe::Tx(s) => spawner.pipes.get_mut(s).unwrap().take_write(),
|
||||
}?;
|
||||
|
||||
Arg::TcpListener { addr } => PreparedArg::TcpListener {
|
||||
socket: TcpListener::bind(addr)?,
|
||||
},
|
||||
builder.keep_fd(&pipe);
|
||||
PreparedArg::Pipe(pipe)
|
||||
}
|
||||
|
||||
Arg::BinaryName => PreparedArg::BinaryName,
|
||||
Arg::Entrypoint => PreparedArg::Entrypoint,
|
||||
Arg::Pipe(p) => PreparedArg::Pipe(p.clone()),
|
||||
Arg::FileSocket(s) => PreparedArg::FileSocket(s.clone()),
|
||||
Arg::Trigger => PreparedArg::Trigger,
|
||||
Arg::Trailing => PreparedArg::Trailing,
|
||||
Arg::FileSocket(s) => {
|
||||
let socket = match s {
|
||||
FileSocket::Rx(s) => spawner.sockets.get_mut(s).unwrap().take_read(),
|
||||
FileSocket::Tx(s) => spawner.sockets.get_mut(s).unwrap().take_write(),
|
||||
}?;
|
||||
|
||||
builder.keep_fd(&socket);
|
||||
PreparedArg::FileSocket(socket)
|
||||
}
|
||||
|
||||
arg => Self::prepare_ambient(builder, arg)?,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete argument preparation in the void
|
||||
*/
|
||||
fn prepare_void_mut(
|
||||
self,
|
||||
spawner: &mut Spawner,
|
||||
entrypoint: &str,
|
||||
trigger: &mut TriggerData,
|
||||
) -> Result<Vec<CString>> {
|
||||
match self {
|
||||
PreparedArg::Pipe(p) => match p {
|
||||
Pipe::Rx(s) => {
|
||||
let pipe = spawner.pipes.get_mut(&s).unwrap().take_read()?;
|
||||
Ok(vec![CString::new(pipe.into_raw_fd().to_string()).unwrap()])
|
||||
}
|
||||
Pipe::Tx(s) => {
|
||||
let pipe = spawner.pipes.get_mut(&s).unwrap().take_write()?;
|
||||
Ok(vec![CString::new(pipe.into_raw_fd().to_string()).unwrap()])
|
||||
}
|
||||
},
|
||||
fn prepare_ambient(builder: &mut VoidBuilder, arg: &Arg) -> Result<Self> {
|
||||
Ok(match arg {
|
||||
Arg::Pipe(p) => return Err(Error::BadPipe(p.get_name().to_string())),
|
||||
Arg::FileSocket(s) => return Err(Error::BadFileSocket(s.get_name().to_string())),
|
||||
|
||||
PreparedArg::FileSocket(s) => match s {
|
||||
FileSocket::Rx(s) => {
|
||||
let pipe = spawner.sockets.get_mut(&s).unwrap().take_read()?;
|
||||
Ok(vec![CString::new(pipe.into_raw_fd().to_string()).unwrap()])
|
||||
}
|
||||
FileSocket::Tx(s) => {
|
||||
let pipe = spawner.sockets.get_mut(&s).unwrap().take_write()?;
|
||||
Ok(vec![CString::new(pipe.into_raw_fd().to_string()).unwrap()])
|
||||
}
|
||||
},
|
||||
Arg::File(path) => {
|
||||
let fd = File::open(path)?;
|
||||
builder.keep_fd(&fd);
|
||||
|
||||
arg => arg.prepare_void(spawner, entrypoint, trigger),
|
||||
}
|
||||
PreparedArg::File(fd)
|
||||
}
|
||||
|
||||
Arg::TcpListener { addr } => {
|
||||
let socket = TcpListener::bind(addr)?;
|
||||
builder.keep_fd(&socket);
|
||||
|
||||
PreparedArg::TcpListener { socket }
|
||||
}
|
||||
|
||||
Arg::BinaryName => PreparedArg::BinaryName,
|
||||
Arg::Entrypoint => PreparedArg::Entrypoint,
|
||||
Arg::Trigger => PreparedArg::Trigger,
|
||||
Arg::Trailing => PreparedArg::Trailing,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,8 +165,10 @@ impl PreparedArg {
|
||||
PreparedArg::BinaryName => Ok(vec![CString::new(spawner.binary).unwrap()]),
|
||||
PreparedArg::Entrypoint => Ok(vec![CString::new(entrypoint).unwrap()]),
|
||||
|
||||
PreparedArg::Pipe(p) => Err(Error::BadPipe(p.get_name().to_string())),
|
||||
PreparedArg::FileSocket(s) => Err(Error::BadFileSocket(s.get_name().to_string())),
|
||||
PreparedArg::Pipe(p) => Ok(vec![CString::new(p.into_raw_fd().to_string()).unwrap()]),
|
||||
PreparedArg::FileSocket(s) => {
|
||||
Ok(vec![CString::new(s.into_raw_fd().to_string()).unwrap()])
|
||||
}
|
||||
|
||||
PreparedArg::File(f) => Ok(vec![CString::new(f.into_raw_fd().to_string()).unwrap()]),
|
||||
|
||||
|
@ -68,11 +68,12 @@ impl<'a> Spawner<'a> {
|
||||
|
||||
self.prepare_env(&mut builder, &entrypoint.environment);
|
||||
|
||||
let args = PreparedArgs::prepare_ambient(&entrypoint.args)?;
|
||||
let args =
|
||||
PreparedArgs::prepare_ambient_mut(self, &mut builder, &entrypoint.args)?;
|
||||
|
||||
let closure = || {
|
||||
let args = args
|
||||
.prepare_void_mut(self, name, &mut TriggerData::None)
|
||||
.prepare_void(self, name, &mut TriggerData::None)
|
||||
.unwrap();
|
||||
|
||||
if let Err(e) = unistd::execv(&CString::new("/entrypoint").unwrap(), &args)
|
||||
@ -162,7 +163,7 @@ impl<'a> Spawner<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
let args = PreparedArgs::prepare_ambient(&spec.args)?;
|
||||
let args = PreparedArgs::prepare_ambient(&mut builder, &spec.args)?;
|
||||
|
||||
let closure =
|
||||
|| {
|
||||
@ -226,7 +227,7 @@ impl<'a> Spawner<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
let args = PreparedArgs::prepare_ambient(&spec.args)?;
|
||||
let args = PreparedArgs::prepare_ambient(&mut builder, &spec.args)?;
|
||||
|
||||
let closure = || {
|
||||
let args = args
|
||||
|
17
src/void.rs
17
src/void.rs
@ -8,6 +8,7 @@ use std::fs;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use nix::fcntl::{FcntlArg, FdFlag};
|
||||
use nix::mount::{mount, umount2, MntFlags, MsFlags};
|
||||
use nix::sched::unshare;
|
||||
use nix::sys::signal::{signal, SigHandler, Signal};
|
||||
@ -103,6 +104,22 @@ impl VoidBuilder {
|
||||
closer.closefrom(3);
|
||||
}
|
||||
|
||||
for fd in keep.as_ref() {
|
||||
let mut flags = FdFlag::from_bits_truncate(
|
||||
nix::fcntl::fcntl(*fd, FcntlArg::F_GETFD).map_err(|e| Error::Nix {
|
||||
msg: "fcntl",
|
||||
src: e,
|
||||
})?,
|
||||
);
|
||||
|
||||
flags.remove(FdFlag::FD_CLOEXEC);
|
||||
|
||||
nix::fcntl::fcntl(*fd, FcntlArg::F_SETFD(flags)).map_err(|e| Error::Nix {
|
||||
msg: "fcntl",
|
||||
src: e,
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user