Fixed -exec{}: dup()"d file descriptor was being closed before the process could access it. Fixed -exec (hack ver.): Ditto.

Fortune for collect's current commit: Small blessing − 小吉
exec
Avril 1 year ago
parent 582bfc0dad
commit 31cfee9989
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -18,9 +18,10 @@ use std::{
fn proc_file<F: ?Sized + AsRawFd>(file: &F) -> PathBuf
{
let fd = file.as_raw_fd();
//let pid = process::id();
//format!("/proc/{pid}/fd/{fd}").into()
format!("/dev/fd/{fd}").into()
let pid = process::id();
//process::Command::new("/bin/ls").arg("-l").arg(format!("/proc/{pid}/fd/")).spawn().unwrap().wait().unwrap();
format!("/proc/{pid}/fd/{fd}").into()
//format!("/dev/fd/{fd}").into()
}
/// Attempt to `dup()` a file descriptor into a `RawFile`.
@ -40,10 +41,10 @@ fn dup_file<F: ?Sized + AsRawFd>(file: &F) -> io::Result<memfile::RawFile>
Ok(memfile::RawFile::take_ownership_of_unchecked(fd))
}
fn run_stdin<I>(file: Option<impl Into<fs::File>>, filename: impl AsRef<OsStr>, args: I) -> io::Result<process::Child>
fn run_stdin<I>(file: Option<impl Into<fs::File>>, filename: impl AsRef<OsStr>, args: I) -> io::Result<(process::Child, Option<fs::File>)>
where I: IntoIterator<Item = OsString>,
{
let file = {
let mut file = {
let file: Option<fs::File> = file.map(Into::into);
//TODO: Do we need to fcntl() this to make it (the fd) RW?
match file {
@ -65,7 +66,8 @@ where I: IntoIterator<Item = OsString>,
.stdout(process::Stdio::inherit())
.stderr(process::Stdio::inherit())
.spawn()?;
if let Some((mut input, mut output)) = file.zip(child.stdin.take()) {
//TODO: XXX: Why does `/proc/{pid}/fd/{fd}` **and** `/dev/fd/{fd}` not work for -exec{}, and why foes `Stdio::from(file)` not work for stdin even *afer* re-seeking the file???
if let Some((mut input, mut output)) = file.as_mut().zip(child.stdin.take()) {
io::copy(&mut input, &mut output)
/*.wrap_err("Failed to pipe file into stdin for child")*/?;
}
@ -75,23 +77,23 @@ where I: IntoIterator<Item = OsString>,
.code()
.unwrap_or(-1)) //XXX: What should we do if the process terminates without a code (i.e. by a signal?)
*/
Ok(child)
Ok((child, file))
}
/// Run a single `-exec` / `-exec{}` and return the (possibly still running) child process if succeeded in spawning.
///
/// The caller must wait for all child processes to exit before the parent does.
#[inline]
pub fn run_single<F: ?Sized + AsRawFd>(file: &F, opt: args::ExecMode) -> io::Result<process::Child>
pub fn run_single<F: ?Sized + AsRawFd>(file: &F, opt: args::ExecMode) -> io::Result<(process::Child, Option<fs::File>)>
{
let input = dup_file(file)?;
let input: std::mem::ManuallyDrop<memfile::RawFile> = std::mem::ManuallyDrop::new(dup_file(file)?);
match opt {
args::ExecMode::Positional { command, args } => {
run_stdin(None::<fs::File>, command, args.into_iter().map(move |x| x.unwrap_or_else(|| proc_file(&input).into())))
run_stdin(None::<fs::File>, command, args.into_iter().map(|x| x.unwrap_or_else(|| proc_file(&*input).into())))
},
args::ExecMode::Stdin { command, args } => {
run_stdin(Some(input), command, args)
run_stdin(Some(std::mem::ManuallyDrop::into_inner(input)), command, args)
}
}
}
@ -100,7 +102,7 @@ pub fn run_single<F: ?Sized + AsRawFd>(file: &F, opt: args::ExecMode) -> io::Res
///
/// # Returns
/// An iterator of each (possibly running) spawned child, or the error that occoured when trying to spawn that child from the `exec` option in `opt`.
pub fn spawn_from<'a, F: ?Sized + AsRawFd>(file: &'a F, opt: Options) -> impl IntoIterator<Item = io::Result<process::Child>> + 'a
pub fn spawn_from<'a, F: ?Sized + AsRawFd>(file: &'a F, opt: Options) -> impl IntoIterator<Item = io::Result<(process::Child, Option<fs::File>)>> + 'a
{
opt.into_opt_exec().map(|x| run_single(file, x))
//todo!("Loop through `opt.into_exec()`, map the call to `|x| run_single(file, x)`, and return that iterator")
@ -120,7 +122,7 @@ pub fn spawn_from_sync<'a, F: ?Sized + AsRawFd>(file: &'a F, opt: Options) -> im
let idx = move || idx.to_string().header("");
match child {
Ok(mut child) => {
Ok(child.wait()
Ok(child.0.wait()
.wrap_err("Failed to wait on child")
.with_note(|| "The child may have detached itself")
.with_section(idx)?

Loading…
Cancel
Save