1use std::{
2 any::Any,
3 io::{Read, Result},
4 process::{Child, ChildStderr, ChildStdin, ChildStdout, Command, ExitStatus, Output},
5};
6
7#[cfg(unix)]
8use nix::{
9 sys::signal::{kill, Signal},
10 unistd::Pid,
11};
12
13crate::generic_wrap::Wrap!(Command, Child, ChildWrapper, |child| child);
14
15pub trait ChildWrapper: Any + std::fmt::Debug + Send {
52 fn inner(&self) -> &dyn ChildWrapper;
54
55 fn inner_mut(&mut self) -> &mut dyn ChildWrapper;
57
58 fn into_inner(self: Box<Self>) -> Box<dyn ChildWrapper>;
64
65 fn try_clone(&self) -> Option<Box<dyn ChildWrapper>> {
70 None
71 }
72
73 fn stdin(&mut self) -> &mut Option<ChildStdin> {
77 self.inner_mut().stdin()
78 }
79
80 fn stdout(&mut self) -> &mut Option<ChildStdout> {
84 self.inner_mut().stdout()
85 }
86
87 fn stderr(&mut self) -> &mut Option<ChildStderr> {
91 self.inner_mut().stderr()
92 }
93
94 fn id(&self) -> u32 {
99 self.inner().id()
100 }
101
102 fn kill(&mut self) -> Result<()> {
108 self.start_kill()?;
109 self.wait()?;
110 Ok(())
111 }
112
113 fn start_kill(&mut self) -> Result<()> {
123 self.inner_mut().start_kill()
124 }
125
126 fn try_wait(&mut self) -> Result<Option<ExitStatus>> {
133 self.inner_mut().try_wait()
134 }
135
136 fn wait(&mut self) -> Result<ExitStatus> {
143 self.inner_mut().wait()
144 }
145
146 fn wait_with_output(mut self: Box<Self>) -> Result<Output>
156 where
157 Self: 'static,
158 {
159 drop(self.stdin().take());
160
161 let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
162 match (self.stdout().take(), self.stderr().take()) {
163 (None, None) => {}
164 (Some(mut out), None) => {
165 let res = out.read_to_end(&mut stdout);
166 res.unwrap();
167 }
168 (None, Some(mut err)) => {
169 let res = err.read_to_end(&mut stderr);
170 res.unwrap();
171 }
172 (Some(out), Some(err)) => {
173 let res = read2(out, &mut stdout, err, &mut stderr);
174 res.unwrap();
175 }
176 }
177
178 let status = self.wait()?;
179 Ok(Output {
180 status,
181 stdout,
182 stderr,
183 })
184 }
185
186 #[cfg(unix)]
192 fn signal(&self, sig: i32) -> Result<()> {
193 self.inner().signal(sig)
194 }
195}
196
197impl ChildWrapper for Child {
198 fn inner(&self) -> &dyn ChildWrapper {
199 self
200 }
201 fn inner_mut(&mut self) -> &mut dyn ChildWrapper {
202 self
203 }
204 fn into_inner(self: Box<Self>) -> Box<dyn ChildWrapper> {
205 self
206 }
207 fn stdin(&mut self) -> &mut Option<ChildStdin> {
208 &mut self.stdin
209 }
210 fn stdout(&mut self) -> &mut Option<ChildStdout> {
211 &mut self.stdout
212 }
213 fn stderr(&mut self) -> &mut Option<ChildStderr> {
214 &mut self.stderr
215 }
216 fn id(&self) -> u32 {
217 Child::id(self)
218 }
219 fn start_kill(&mut self) -> Result<()> {
220 #[cfg(unix)]
221 {
222 self.signal(Signal::SIGKILL as _)
223 }
224
225 #[cfg(not(unix))]
226 {
227 Child::kill(self)
228 }
229 }
230 fn try_wait(&mut self) -> Result<Option<ExitStatus>> {
231 Child::try_wait(self)
232 }
233 fn wait(&mut self) -> Result<ExitStatus> {
234 Child::wait(self)
235 }
236 #[cfg(unix)]
237 fn signal(&self, sig: i32) -> Result<()> {
238 kill(
239 Pid::from_raw(i32::try_from(self.id()).map_err(std::io::Error::other)?),
240 Signal::try_from(sig)?,
241 )
242 .map_err(std::io::Error::from)
243 }
244}
245
246impl dyn ChildWrapper {
247 fn downcast_ref<T: 'static>(&self) -> Option<&T> {
248 (self as &dyn Any).downcast_ref()
249 }
250
251 fn is_raw_child(&self) -> bool {
252 self.downcast_ref::<Child>().is_some()
253 }
254
255 pub fn inner_child(&self) -> &Child {
257 let mut inner = self;
258 while !inner.is_raw_child() {
259 inner = inner.inner();
260 }
261
262 inner.downcast_ref().unwrap()
264 }
265
266 pub unsafe fn inner_child_mut(&mut self) -> &mut Child {
270 let mut inner = self;
271 while !inner.is_raw_child() {
272 inner = inner.inner_mut();
273 }
274
275 (inner as &mut dyn Any).downcast_mut().unwrap()
277 }
278
279 pub unsafe fn into_inner_child(self: Box<Self>) -> Child {
283 let mut inner = self;
284 while !inner.is_raw_child() {
285 inner = inner.into_inner();
286 }
287
288 *(inner as Box<dyn Any>).downcast().unwrap()
290 }
291}
292
293#[cfg(unix)]
294fn read2(
295 mut out_r: ChildStdout,
296 out_v: &mut Vec<u8>,
297 mut err_r: ChildStderr,
298 err_v: &mut Vec<u8>,
299) -> Result<()> {
300 use nix::{
301 errno::Errno,
302 libc,
303 poll::{poll, PollFd, PollFlags, PollTimeout},
304 };
305 use std::{
306 io::Error,
307 os::fd::{AsRawFd, BorrowedFd},
308 };
309
310 let out_fd = out_r.as_raw_fd();
311 let err_fd = err_r.as_raw_fd();
312 let out_bfd = unsafe { BorrowedFd::borrow_raw(out_fd) };
314 let err_bfd = unsafe { BorrowedFd::borrow_raw(err_fd) };
315
316 set_nonblocking(out_bfd, true)?;
317 set_nonblocking(err_bfd, true)?;
318
319 let mut fds = [
320 PollFd::new(out_bfd, PollFlags::POLLIN),
321 PollFd::new(err_bfd, PollFlags::POLLIN),
322 ];
323
324 loop {
325 poll(&mut fds, PollTimeout::NONE)?;
326
327 if fds[0].revents().is_some() && read(&mut out_r, out_v)? {
328 set_nonblocking(err_bfd, false)?;
329 return err_r.read_to_end(err_v).map(drop);
330 }
331 if fds[1].revents().is_some() && read(&mut err_r, err_v)? {
332 set_nonblocking(out_bfd, false)?;
333 return out_r.read_to_end(out_v).map(drop);
334 }
335 }
336
337 fn read(r: &mut impl Read, dst: &mut Vec<u8>) -> Result<bool> {
338 match r.read_to_end(dst) {
339 Ok(_) => Ok(true),
340 Err(e) => {
341 if e.raw_os_error() == Some(libc::EWOULDBLOCK)
342 || e.raw_os_error() == Some(libc::EAGAIN)
343 {
344 Ok(false)
345 } else {
346 Err(e)
347 }
348 }
349 }
350 }
351
352 #[cfg(target_os = "linux")]
353 fn set_nonblocking(fd: BorrowedFd, nonblocking: bool) -> Result<()> {
354 let v = nonblocking as libc::c_int;
355 let res = unsafe { libc::ioctl(fd.as_raw_fd(), libc::FIONBIO, &v) };
356
357 Errno::result(res).map_err(Error::from).map(drop)
358 }
359
360 #[cfg(not(target_os = "linux"))]
361 fn set_nonblocking(fd: BorrowedFd, nonblocking: bool) -> Result<()> {
362 use nix::fcntl::{fcntl, FcntlArg, OFlag};
363
364 let mut flags = OFlag::from_bits_truncate(fcntl(fd, FcntlArg::F_GETFL)?);
365 flags.set(OFlag::O_NONBLOCK, nonblocking);
366
367 fcntl(fd, FcntlArg::F_SETFL(flags))
368 .map_err(Error::from)
369 .map(drop)
370 }
371}
372
373#[cfg(not(unix))]
376fn read2(
377 mut out_r: ChildStdout,
378 out_v: &mut Vec<u8>,
379 mut err_r: ChildStderr,
380 err_v: &mut Vec<u8>,
381) -> Result<()> {
382 out_r.read_to_end(out_v)?;
383 err_r.read_to_end(err_v)?;
384 Ok(())
385}