alnyan/yggdrasil: better fd handling in Command

This commit is contained in:
2024-01-04 23:58:12 +02:00
parent 4223772986
commit 64c8a5cab9
3 changed files with 37 additions and 75 deletions
+3 -3
View File
@@ -55,10 +55,10 @@ pub unsafe fn mount_raw(options: &MountOptions<'_>) -> crate::io::Result<()> {
} }
#[unstable(feature = "yggdrasil_os", issue = "none")] #[unstable(feature = "yggdrasil_os", issue = "none")]
pub fn create_pipe_pair() -> crate::io::Result<(RawFd, RawFd)> { pub fn create_pipe_pair() -> crate::io::Result<(OwnedFd, OwnedFd)> {
let mut buffer = MaybeUninit::uninit_array(); let mut buffer = MaybeUninit::uninit_array();
cvt_io(unsafe { syscall::create_pipe(&mut buffer) })?; cvt_io(unsafe { syscall::create_pipe(&mut buffer) })?;
let read = unsafe { buffer[0].assume_init() }; let read = unsafe { OwnedFd::from_raw_fd(buffer[0].assume_init()) };
let write = unsafe { buffer[1].assume_init() }; let write = unsafe { OwnedFd::from_raw_fd(buffer[1].assume_init()) };
Ok((read, write)) Ok((read, write))
} }
+4 -12
View File
@@ -1,5 +1,5 @@
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::os::yggdrasil::io::{AsRawFd, FromRawFd, RawFd}; use crate::os::yggdrasil::io::{AsRawFd, FromRawFd, OwnedFd, RawFd};
use crate::sys::cvt_io; use crate::sys::cvt_io;
use crate::sys::io::FileDesc; use crate::sys::io::FileDesc;
@@ -39,23 +39,15 @@ impl AnonPipe {
} }
} }
impl FromRawFd for AnonPipe {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self(FileDesc::from_raw_fd(fd))
}
}
impl AsRawFd for AnonPipe { impl AsRawFd for AnonPipe {
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd() self.0.as_raw_fd()
} }
} }
impl Drop for AnonPipe { impl From<OwnedFd> for AnonPipe {
fn drop(&mut self) { fn from(_fd: OwnedFd) -> Self {
unsafe { todo!()
// yggdrasil_rt::sys::close(self.as_raw_fd()).ok();
}
} }
} }
+30 -60
View File
@@ -2,7 +2,7 @@ use crate::ffi::OsStr;
use crate::fmt; use crate::fmt;
use crate::io; use crate::io;
use crate::num::NonZeroI32; use crate::num::NonZeroI32;
use crate::os::yggdrasil::io::{AsRawFd, FromRawFd, IntoRawFd}; use crate::os::yggdrasil::io::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd};
use crate::path::Path; use crate::path::Path;
use crate::sys::cvt_io; use crate::sys::cvt_io;
use crate::sys::fd::FileDesc; use crate::sys::fd::FileDesc;
@@ -35,11 +35,12 @@ pub struct ChildPipes {
pub stderr: ChildStdio, pub stderr: ChildStdio,
} }
#[derive(Debug, PartialEq)] #[derive(Debug)]
pub enum ChildStdio { pub enum ChildStdio {
Inherit, Inherit,
Null, Null,
Fd(RawFd), RawFd(RawFd),
OwnedFd(OwnedFd),
} }
#[derive(Debug)] #[derive(Debug)]
@@ -47,7 +48,8 @@ pub enum Stdio {
Inherit, Inherit,
Null, Null,
MakePipe, MakePipe,
Fd(FileDesc), RawFd(RawFd),
OwnedFd(FileDesc),
} }
pub struct Process { pub struct Process {
@@ -79,8 +81,7 @@ impl Process {
impl FromRawFd for crate::process::Stdio { impl FromRawFd for crate::process::Stdio {
#[inline] #[inline]
unsafe fn from_raw_fd(fd: RawFd) -> crate::process::Stdio { unsafe fn from_raw_fd(fd: RawFd) -> crate::process::Stdio {
let fd = FileDesc::from_raw_fd(fd); let io = Stdio::RawFd(fd);
let io = Stdio::Fd(fd);
crate::process::Stdio::from_inner(io) crate::process::Stdio::from_inner(io)
} }
} }
@@ -94,24 +95,15 @@ impl Stdio {
let (read, write) = crate::os::yggdrasil::io::create_pipe_pair()?; let (read, write) = crate::os::yggdrasil::io::create_pipe_pair()?;
if readable { if readable {
yggdrasil_rt::debug_trace!( let write = unsafe { AnonPipe::from(write) };
"--- Make pipes for MakePipe: to_child={:?}, to_parent={:?} ---", Ok((ChildStdio::OwnedFd(read), Some(write)))
read,
write
);
let write = unsafe { AnonPipe::from_raw_fd(write) };
Ok((ChildStdio::Fd(read), Some(write)))
} else { } else {
yggdrasil_rt::debug_trace!( let read = unsafe { AnonPipe::from(read) };
"--- Make pipes for MakePipe: to_child={:?}, to_parent={:?} ---", Ok((ChildStdio::OwnedFd(write), Some(read)))
write,
read
);
let read = unsafe { AnonPipe::from_raw_fd(read) };
Ok((ChildStdio::Fd(write), Some(read)))
} }
} }
Stdio::Fd(fd) => Ok((ChildStdio::Fd(fd.as_raw_fd()), None)), Stdio::OwnedFd(fd) => Ok((ChildStdio::RawFd(fd.as_raw_fd()), None)),
Stdio::RawFd(fd) => Ok((ChildStdio::RawFd(*fd), None)),
} }
} }
} }
@@ -128,6 +120,17 @@ impl From<File> for Stdio {
} }
} }
impl ChildStdio {
fn as_raw_fd_or_default(&self, default: RawFd) -> Option<RawFd> {
match self {
Self::Null => None,
Self::Inherit => Some(default),
Self::OwnedFd(fd) => Some(fd.as_raw_fd()),
Self::RawFd(fd) => Some(*fd),
}
}
}
// Status // Status
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, PartialEq, Eq)]
@@ -240,7 +243,6 @@ impl Command {
} }
pub fn stdin(&mut self, stdin: Stdio) { pub fn stdin(&mut self, stdin: Stdio) {
yggdrasil_rt::debug_trace!("!!! Override stdin: {:?}", stdin);
self.stdin = stdin; self.stdin = stdin;
} }
@@ -273,21 +275,12 @@ impl Command {
default: Stdio, default: Stdio,
needs_stdin: bool, needs_stdin: bool,
) -> io::Result<(Process, StdioPipes)> { ) -> io::Result<(Process, StdioPipes)> {
yggdrasil_rt::debug_trace!("Default: {:?}, needs_stdin = {:?}", default, needs_stdin);
let default_stdin = if needs_stdin { &default } else { &self.stdin }; let default_stdin = if needs_stdin { &default } else { &self.stdin };
let stdin = &self.stdin; let stdin = &self.stdin;
let stdout = &self.stdout; let stdout = &self.stdout;
let stderr = &self.stderr; let stderr = &self.stderr;
yggdrasil_rt::debug_trace!(
"stdin = {:?}, stdout = {:?}, stderr = {:?}",
stdin,
stdout,
stderr
);
let (their_stdin, our_stdin) = stdin.to_child_stdio(true)?; let (their_stdin, our_stdin) = stdin.to_child_stdio(true)?;
let (their_stdout, our_stdout) = stdout.to_child_stdio(false)?; let (their_stdout, our_stdout) = stdout.to_child_stdio(false)?;
let (their_stderr, our_stderr) = stderr.to_child_stdio(false)?; let (their_stderr, our_stderr) = stderr.to_child_stdio(false)?;
@@ -295,8 +288,6 @@ impl Command {
let ours = StdioPipes { stdin: our_stdin, stdout: our_stdout, stderr: our_stderr }; let ours = StdioPipes { stdin: our_stdin, stdout: our_stdout, stderr: our_stderr };
let theirs = ChildPipes { stdin: their_stdin, stdout: their_stdout, stderr: their_stderr }; let theirs = ChildPipes { stdin: their_stdin, stdout: their_stdout, stderr: their_stderr };
yggdrasil_rt::debug_trace!("theirs = {:?}", theirs);
let process = self.do_spawn(&theirs)?; let process = self.do_spawn(&theirs)?;
Ok((process, ours)) Ok((process, ours))
@@ -309,35 +300,14 @@ impl Command {
fn do_spawn(&mut self, pipes: &ChildPipes) -> io::Result<Process> { fn do_spawn(&mut self, pipes: &ChildPipes) -> io::Result<Process> {
let mut optional = Vec::new(); let mut optional = Vec::new();
if pipes.stdin != ChildStdio::Null { if let Some(fd) = pipes.stdin.as_raw_fd_or_default(RawFd::STDIN) {
optional.push(SpawnOption::InheritFile { optional.push(SpawnOption::InheritFile { source: fd, child: RawFd::STDIN });
source: match pipes.stdin {
ChildStdio::Inherit => RawFd::STDIN,
ChildStdio::Fd(fd) => fd,
ChildStdio::Null => todo!(),
},
child: RawFd::STDIN,
});
} }
if pipes.stdout != ChildStdio::Null { if let Some(fd) = pipes.stdout.as_raw_fd_or_default(RawFd::STDOUT) {
optional.push(SpawnOption::InheritFile { optional.push(SpawnOption::InheritFile { source: fd, child: RawFd::STDOUT });
source: match pipes.stdout {
ChildStdio::Inherit => RawFd::STDOUT,
ChildStdio::Fd(fd) => fd,
ChildStdio::Null => todo!(),
},
child: RawFd::STDOUT,
});
} }
if pipes.stderr != ChildStdio::Null { if let Some(fd) = pipes.stderr.as_raw_fd_or_default(RawFd::STDERR) {
optional.push(SpawnOption::InheritFile { optional.push(SpawnOption::InheritFile { source: fd, child: RawFd::STDERR });
source: match pipes.stderr {
ChildStdio::Inherit => RawFd::STDERR,
ChildStdio::Fd(fd) => fd,
ChildStdio::Null => todo!(),
},
child: RawFd::STDERR,
});
} }
if let Some(pgroup) = self.pgroup { if let Some(pgroup) = self.pgroup {