|
2 | 2 | //! |
3 | 3 | //! See the [`new`] function for documentation. |
4 | 4 |
|
| 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! { |
5 | 77 | 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}; |
8 | 80 | use std::process::{ChildStderr, ChildStdin, ChildStdout}; |
9 | 81 |
|
10 | 82 | use crate::io_source::IoSource; |
@@ -145,74 +217,10 @@ use crate::{event, Interest, Registry, Token}; |
145 | 217 | /// # } |
146 | 218 | /// ``` |
147 | 219 | 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. |
213 | 222 | let r = unsafe { Receiver::from_raw_fd(fds[0]) }; |
214 | 223 | let w = unsafe { Sender::from_raw_fd(fds[1]) }; |
215 | | - |
216 | 224 | Ok((w, r)) |
217 | 225 | } |
218 | 226 |
|
@@ -579,3 +587,4 @@ fn set_nonblocking(fd: RawFd, nonblocking: bool) -> io::Result<()> { |
579 | 587 |
|
580 | 588 | Ok(()) |
581 | 589 | } |
| 590 | +} // `cfg_os_ext!`. |
0 commit comments