Skip to content

Commit 9f21ce1

Browse files
committed
Enable sys::unix::pipe when using pipe based Waker
This also adds a new function sys::unix::pipe::new_raw that creates a pipe, returning the raw fds. This is used by the Waker implementation and of course sys::unix::pipe::new (which is exposed as mio::unix::pipe::new).
1 parent e7a0685 commit 9f21ce1

File tree

3 files changed

+94
-75
lines changed

3 files changed

+94
-75
lines changed

src/sys/unix/mod.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,19 @@ cfg_os_poll! {
9494
pub(crate) use self::selector::IoSourceState;
9595
}
9696

97-
cfg_os_ext! {
98-
pub(crate) mod pipe;
99-
}
97+
#[cfg(any(
98+
// For the public `pipe` module, must match `cfg_os_ext` macro.
99+
feature = "os-ext",
100+
// For the `Waker` type based on a pipe.
101+
mio_unsupported_force_waker_pipe,
102+
target_os = "aix",
103+
target_os = "dragonfly",
104+
target_os = "illumos",
105+
target_os = "netbsd",
106+
target_os = "openbsd",
107+
target_os = "redox",
108+
))]
109+
pub(crate) mod pipe;
100110
}
101111

102112
cfg_not_os_poll! {

src/sys/unix/pipe.rs

Lines changed: 77 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,81 @@
22
//!
33
//! See the [`new`] function for documentation.
44
5+
use std::io;
6+
use std::os::unix::io::RawFd;
7+
8+
pub(crate) fn new_raw() -> io::Result<[RawFd; 2]> {
9+
let mut fds: [RawFd; 2] = [-1, -1];
10+
11+
#[cfg(any(
12+
target_os = "android",
13+
target_os = "dragonfly",
14+
target_os = "freebsd",
15+
target_os = "linux",
16+
target_os = "netbsd",
17+
target_os = "openbsd",
18+
target_os = "illumos",
19+
target_os = "redox",
20+
))]
21+
unsafe {
22+
if libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC | libc::O_NONBLOCK) != 0 {
23+
return Err(io::Error::last_os_error());
24+
}
25+
}
26+
27+
#[cfg(any(
28+
target_os = "aix",
29+
target_os = "ios",
30+
target_os = "macos",
31+
target_os = "tvos",
32+
target_os = "watchos",
33+
target_os = "espidf",
34+
))]
35+
unsafe {
36+
// For platforms that don't have `pipe2(2)` we need to manually set the
37+
// correct flags on the file descriptor.
38+
if libc::pipe(fds.as_mut_ptr()) != 0 {
39+
return Err(io::Error::last_os_error());
40+
}
41+
42+
for fd in &fds {
43+
if libc::fcntl(*fd, libc::F_SETFL, libc::O_NONBLOCK) != 0
44+
|| libc::fcntl(*fd, libc::F_SETFD, libc::FD_CLOEXEC) != 0
45+
{
46+
let err = io::Error::last_os_error();
47+
// Don't leak file descriptors. Can't handle closing error though.
48+
let _ = libc::close(fds[0]);
49+
let _ = libc::close(fds[1]);
50+
return Err(err);
51+
}
52+
}
53+
}
54+
55+
#[cfg(not(any(
56+
target_os = "aix",
57+
target_os = "android",
58+
target_os = "dragonfly",
59+
target_os = "freebsd",
60+
target_os = "illumos",
61+
target_os = "ios",
62+
target_os = "linux",
63+
target_os = "macos",
64+
target_os = "netbsd",
65+
target_os = "openbsd",
66+
target_os = "redox",
67+
target_os = "tvos",
68+
target_os = "watchos",
69+
target_os = "espidf",
70+
)))]
71+
compile_error!("unsupported target for `mio::unix::pipe`");
72+
73+
Ok(fds)
74+
}
75+
76+
cfg_os_ext! {
577
use std::fs::File;
6-
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
7-
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
78+
use std::io::{IoSlice, IoSliceMut, Read, Write};
79+
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
880
use std::process::{ChildStderr, ChildStdin, ChildStdout};
981

1082
use crate::io_source::IoSource;
@@ -145,74 +217,10 @@ use crate::{event, Interest, Registry, Token};
145217
/// # }
146218
/// ```
147219
pub fn new() -> io::Result<(Sender, Receiver)> {
148-
let mut fds: [RawFd; 2] = [-1, -1];
149-
150-
#[cfg(any(
151-
target_os = "android",
152-
target_os = "dragonfly",
153-
target_os = "freebsd",
154-
target_os = "linux",
155-
target_os = "netbsd",
156-
target_os = "openbsd",
157-
target_os = "illumos",
158-
target_os = "redox",
159-
))]
160-
unsafe {
161-
if libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC | libc::O_NONBLOCK) != 0 {
162-
return Err(io::Error::last_os_error());
163-
}
164-
}
165-
166-
#[cfg(any(
167-
target_os = "aix",
168-
target_os = "ios",
169-
target_os = "macos",
170-
target_os = "tvos",
171-
target_os = "watchos",
172-
target_os = "espidf",
173-
))]
174-
unsafe {
175-
// For platforms that don't have `pipe2(2)` we need to manually set the
176-
// correct flags on the file descriptor.
177-
if libc::pipe(fds.as_mut_ptr()) != 0 {
178-
return Err(io::Error::last_os_error());
179-
}
180-
181-
for fd in &fds {
182-
if libc::fcntl(*fd, libc::F_SETFL, libc::O_NONBLOCK) != 0
183-
|| libc::fcntl(*fd, libc::F_SETFD, libc::FD_CLOEXEC) != 0
184-
{
185-
let err = io::Error::last_os_error();
186-
// Don't leak file descriptors. Can't handle closing error though.
187-
let _ = libc::close(fds[0]);
188-
let _ = libc::close(fds[1]);
189-
return Err(err);
190-
}
191-
}
192-
}
193-
194-
#[cfg(not(any(
195-
target_os = "aix",
196-
target_os = "android",
197-
target_os = "dragonfly",
198-
target_os = "freebsd",
199-
target_os = "illumos",
200-
target_os = "ios",
201-
target_os = "linux",
202-
target_os = "macos",
203-
target_os = "netbsd",
204-
target_os = "openbsd",
205-
target_os = "redox",
206-
target_os = "tvos",
207-
target_os = "watchos",
208-
target_os = "espidf",
209-
)))]
210-
compile_error!("unsupported target for `mio::unix::pipe`");
211-
212-
// SAFETY: we just initialised the `fds` above.
220+
let fds = new_raw()?;
221+
// SAFETY: `new_raw` initialised the `fds` above.
213222
let r = unsafe { Receiver::from_raw_fd(fds[0]) };
214223
let w = unsafe { Sender::from_raw_fd(fds[1]) };
215-
216224
Ok((w, r))
217225
}
218226

@@ -579,3 +587,4 @@ fn set_nonblocking(fd: RawFd, nonblocking: bool) -> io::Result<()> {
579587

580588
Ok(())
581589
}
590+
} // `cfg_os_ext!`.

src/sys/unix/waker.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ pub use self::kqueue::Waker;
207207
target_os = "redox",
208208
))]
209209
mod pipe {
210-
use crate::unix::pipe::new as new_pipe;
210+
use crate::sys::unix::pipe;
211211
use std::fs::File;
212212
use std::io::{self, Read, Write};
213213
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
@@ -224,9 +224,9 @@ mod pipe {
224224

225225
impl WakerInternal {
226226
pub fn new() -> io::Result<WakerInternal> {
227-
let (sender, receiver) = new_pipe()?;
228-
let sender = unsafe { File::from_raw_fd(sender.as_raw_fd()) };
229-
let receiver = unsafe { File::from_raw_fd(receiver.as_raw_fd()) };
227+
let [sender, receiver] = pipe::new_raw()?;
228+
let sender = unsafe { File::from_raw_fd(sender) };
229+
let receiver = unsafe { File::from_raw_fd(receiver) };
230230
Ok(WakerInternal { sender, receiver })
231231
}
232232

0 commit comments

Comments
 (0)