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