1 use crate::io
::{self, IoSlice, IoSliceMut}
;
3 use crate::sync
::atomic
::AtomicBool
;
4 use crate::sys
::fd
::FileDesc
;
5 use crate::sys
::{cvt, cvt_r}
;
6 use libc
::{self /*, c_int apparently not used? */}
;
8 pub struct AnonPipe(FileDesc
);
10 pub fn anon_pipe() -> io
::Result
<(AnonPipe
, AnonPipe
)> {
11 static INVALID
: AtomicBool
= AtomicBool
::new(false);
14 cvt(unsafe { libc::pipe(fds.as_mut_ptr()) }
)?
;
16 let fd0
= FileDesc
::new(fds
[0]);
17 let fd1
= FileDesc
::new(fds
[1]);
20 Ok((AnonPipe(fd0
), AnonPipe(fd1
)))
24 pub fn read(&self, buf
: &mut [u8]) -> io
::Result
<usize> {
27 pub fn read_vectored(&self, bufs
: &mut [IoSliceMut
<'_
>]) -> io
::Result
<usize> {
28 self.0.read_vectored(bufs
)
31 pub fn write(&self, buf
: &[u8]) -> io
::Result
<usize> {
35 pub fn write_vectored(&self, bufs
: &[IoSlice
<'_
>]) -> io
::Result
<usize> {
36 self.0.write_vectored(bufs
)
39 pub fn fd(&self) -> &FileDesc
{
42 pub fn into_fd(self) -> FileDesc
{
45 pub fn diverge(&self) -> ! {
50 pub fn read2(p1
: AnonPipe
, v1
: &mut Vec
<u8>, p2
: AnonPipe
, v2
: &mut Vec
<u8>) -> io
::Result
<()> {
51 // Set both pipes into nonblocking mode as we're gonna be reading from both
52 // in the `select` loop below, and we wouldn't want one to block the other!
53 let p1
= p1
.into_fd();
54 let p2
= p2
.into_fd();
55 p1
.set_nonblocking_pipe(true)?
;
56 p2
.set_nonblocking_pipe(true)?
;
58 let mut fds
: [libc
::pollfd
; 2] = unsafe { mem::zeroed() }
;
60 fds
[0].events
= libc
::POLLIN
;
62 fds
[1].events
= libc
::POLLIN
;
64 // wait for either pipe to become readable using `poll`
65 cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) }
)?
;
67 if fds
[0].revents
!= 0 && read(&p1
, v1
)?
{
68 p2
.set_nonblocking_pipe(false)?
;
69 return p2
.read_to_end(v2
).map(|_
| ());
71 if fds
[1].revents
!= 0 && read(&p2
, v2
)?
{
72 p1
.set_nonblocking_pipe(false)?
;
73 return p1
.read_to_end(v1
).map(|_
| ());
77 // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
78 // EAGAIN. If we hit EOF, then this will happen because the underlying
79 // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
80 // this case we flip the other fd back into blocking mode and read
81 // whatever's leftover on that file descriptor.
82 fn read(fd
: &FileDesc
, dst
: &mut Vec
<u8>) -> Result
<bool
, io
::Error
> {
83 match fd
.read_to_end(dst
) {
86 if e
.raw_os_error() == Some(libc
::EWOULDBLOCK
)
87 || e
.raw_os_error() == Some(libc
::EAGAIN
)