alnyan/yggdrasil: better fd handling in Command
This commit is contained in:
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user