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")]
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();
cvt_io(unsafe { syscall::create_pipe(&mut buffer) })?;
let read = unsafe { buffer[0].assume_init() };
let write = unsafe { buffer[1].assume_init() };
let read = unsafe { OwnedFd::from_raw_fd(buffer[0].assume_init()) };
let write = unsafe { OwnedFd::from_raw_fd(buffer[1].assume_init()) };
Ok((read, write))
}
+4 -12
View File
@@ -1,5 +1,5 @@
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::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 {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
impl Drop for AnonPipe {
fn drop(&mut self) {
unsafe {
// yggdrasil_rt::sys::close(self.as_raw_fd()).ok();
}
impl From<OwnedFd> for AnonPipe {
fn from(_fd: OwnedFd) -> Self {
todo!()
}
}
+30 -60
View File
@@ -2,7 +2,7 @@ use crate::ffi::OsStr;
use crate::fmt;
use crate::io;
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::sys::cvt_io;
use crate::sys::fd::FileDesc;
@@ -35,11 +35,12 @@ pub struct ChildPipes {
pub stderr: ChildStdio,
}
#[derive(Debug, PartialEq)]
#[derive(Debug)]
pub enum ChildStdio {
Inherit,
Null,
Fd(RawFd),
RawFd(RawFd),
OwnedFd(OwnedFd),
}
#[derive(Debug)]
@@ -47,7 +48,8 @@ pub enum Stdio {
Inherit,
Null,
MakePipe,
Fd(FileDesc),
RawFd(RawFd),
OwnedFd(FileDesc),
}
pub struct Process {
@@ -79,8 +81,7 @@ impl Process {
impl FromRawFd for crate::process::Stdio {
#[inline]
unsafe fn from_raw_fd(fd: RawFd) -> crate::process::Stdio {
let fd = FileDesc::from_raw_fd(fd);
let io = Stdio::Fd(fd);
let io = Stdio::RawFd(fd);
crate::process::Stdio::from_inner(io)
}
}
@@ -94,24 +95,15 @@ impl Stdio {
let (read, write) = crate::os::yggdrasil::io::create_pipe_pair()?;
if readable {
yggdrasil_rt::debug_trace!(
"--- Make pipes for MakePipe: to_child={:?}, to_parent={:?} ---",
read,
write
);
let write = unsafe { AnonPipe::from_raw_fd(write) };
Ok((ChildStdio::Fd(read), Some(write)))
let write = unsafe { AnonPipe::from(write) };
Ok((ChildStdio::OwnedFd(read), Some(write)))
} else {
yggdrasil_rt::debug_trace!(
"--- Make pipes for MakePipe: to_child={:?}, to_parent={:?} ---",
write,
read
);
let read = unsafe { AnonPipe::from_raw_fd(read) };
Ok((ChildStdio::Fd(write), Some(read)))
let read = unsafe { AnonPipe::from(read) };
Ok((ChildStdio::OwnedFd(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
#[derive(Clone, Copy, PartialEq, Eq)]
@@ -240,7 +243,6 @@ impl Command {
}
pub fn stdin(&mut self, stdin: Stdio) {
yggdrasil_rt::debug_trace!("!!! Override stdin: {:?}", stdin);
self.stdin = stdin;
}
@@ -273,21 +275,12 @@ impl Command {
default: Stdio,
needs_stdin: bool,
) -> 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 stdin = &self.stdin;
let stdout = &self.stdout;
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_stdout, our_stdout) = stdout.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 theirs = ChildPipes { stdin: their_stdin, stdout: their_stdout, stderr: their_stderr };
yggdrasil_rt::debug_trace!("theirs = {:?}", theirs);
let process = self.do_spawn(&theirs)?;
Ok((process, ours))
@@ -309,35 +300,14 @@ impl Command {
fn do_spawn(&mut self, pipes: &ChildPipes) -> io::Result<Process> {
let mut optional = Vec::new();
if pipes.stdin != ChildStdio::Null {
optional.push(SpawnOption::InheritFile {
source: match pipes.stdin {
ChildStdio::Inherit => RawFd::STDIN,
ChildStdio::Fd(fd) => fd,
ChildStdio::Null => todo!(),
},
child: RawFd::STDIN,
});
if let Some(fd) = pipes.stdin.as_raw_fd_or_default(RawFd::STDIN) {
optional.push(SpawnOption::InheritFile { source: fd, child: RawFd::STDIN });
}
if pipes.stdout != ChildStdio::Null {
optional.push(SpawnOption::InheritFile {
source: match pipes.stdout {
ChildStdio::Inherit => RawFd::STDOUT,
ChildStdio::Fd(fd) => fd,
ChildStdio::Null => todo!(),
},
child: RawFd::STDOUT,
});
if let Some(fd) = pipes.stdout.as_raw_fd_or_default(RawFd::STDOUT) {
optional.push(SpawnOption::InheritFile { source: fd, child: RawFd::STDOUT });
}
if pipes.stderr != ChildStdio::Null {
optional.push(SpawnOption::InheritFile {
source: match pipes.stderr {
ChildStdio::Inherit => RawFd::STDERR,
ChildStdio::Fd(fd) => fd,
ChildStdio::Null => todo!(),
},
child: RawFd::STDERR,
});
if let Some(fd) = pipes.stderr.as_raw_fd_or_default(RawFd::STDERR) {
optional.push(SpawnOption::InheritFile { source: fd, child: RawFd::STDERR });
}
if let Some(pgroup) = self.pgroup {