1use super::signal;
20use super::ChildProcessStarter;
21use super::Dir;
22use super::Disposition;
23use super::Errno;
24use super::FdFlag;
25use super::Gid;
26use super::LimitPair;
27use super::Mode;
28use super::OfdAccess;
29use super::OpenFlag;
30use super::Path;
31use super::PathBuf;
32use super::Resource;
33use super::Result;
34use super::SelectSystem;
35use super::SigmaskOp;
36use super::SignalStatus;
37use super::SignalSystem;
38use super::Stat;
39use super::System;
40use super::SystemEx;
41use super::Times;
42use super::Uid;
43use super::UnixString;
44use crate::io::Fd;
45use crate::job::Pid;
46use crate::job::ProcessState;
47#[cfg(doc)]
48use crate::Env;
49use enumset::EnumSet;
50use std::cell::RefCell;
51use std::convert::Infallible;
52use std::ffi::c_int;
53use std::ffi::CStr;
54use std::ffi::CString;
55use std::future::poll_fn;
56use std::future::Future;
57use std::io::SeekFrom;
58use std::pin::Pin;
59use std::rc::Rc;
60use std::task::Poll;
61use std::time::Duration;
62use std::time::Instant;
63
64#[derive(Clone, Debug)]
124pub struct SharedSystem(pub(super) Rc<RefCell<SelectSystem>>);
125
126impl SharedSystem {
127 pub fn new(system: Box<dyn System>) -> Self {
129 SharedSystem(Rc::new(RefCell::new(SelectSystem::new(system))))
130 }
131
132 pub async fn read_async(&self, fd: Fd, buffer: &mut [u8]) -> Result<usize> {
137 let was_nonblocking = (&mut &*self).get_and_set_nonblocking(fd, true)?;
138
139 let waker = Rc::new(RefCell::new(None));
144
145 let result = poll_fn(|context| {
146 let mut inner = self.0.borrow_mut();
147 match inner.read(fd, buffer) {
148 Err(Errno::EAGAIN) => {
149 *waker.borrow_mut() = Some(context.waker().clone());
150 inner.add_reader(fd, Rc::downgrade(&waker));
151 Poll::Pending
152 }
153 result => Poll::Ready(result),
154 }
155 })
156 .await;
157
158 _ = (&mut &*self).get_and_set_nonblocking(fd, was_nonblocking);
159
160 result
161 }
162
163 pub async fn write_all(&self, fd: Fd, mut buffer: &[u8]) -> Result<usize> {
172 if buffer.is_empty() {
173 return Ok(0);
174 }
175
176 let was_nonblocking = (&mut &*self).get_and_set_nonblocking(fd, true)?;
177 let mut written = 0;
178
179 let waker = Rc::new(RefCell::new(None));
184
185 let result = poll_fn(|context| {
186 let mut inner = self.0.borrow_mut();
187 match inner.write(fd, buffer) {
188 Ok(count) => {
189 written += count;
190 buffer = &buffer[count..];
191 if buffer.is_empty() {
192 return Poll::Ready(Ok(written));
193 }
194 }
195 Err(Errno::EAGAIN | Errno::EINTR) => (),
196 Err(error) => return Poll::Ready(Err(error)),
197 }
198
199 *waker.borrow_mut() = Some(context.waker().clone());
200 inner.add_writer(fd, Rc::downgrade(&waker));
201 Poll::Pending
202 })
203 .await;
204
205 _ = (&mut &*self).get_and_set_nonblocking(fd, was_nonblocking);
206
207 result
208 }
209
210 pub async fn print_error(&self, message: &str) {
212 _ = self.write_all(Fd::STDERR, message.as_bytes()).await;
213 }
214
215 pub async fn wait_until(&self, target: Instant) {
217 let waker = Rc::new(RefCell::new(None));
222
223 poll_fn(|context| {
224 let mut system = self.0.borrow_mut();
225 let now = system.now();
226 if now >= target {
227 return Poll::Ready(());
228 }
229 *waker.borrow_mut() = Some(context.waker().clone());
230 system.add_timeout(target, Rc::downgrade(&waker));
231 Poll::Pending
232 })
233 .await
234 }
235
236 pub async fn wait_for_signals(&self) -> Rc<[signal::Number]> {
248 let status = self.0.borrow_mut().add_signal_waker();
249 poll_fn(|context| {
250 let mut status = status.borrow_mut();
251 let dummy_status = SignalStatus::Expected(None);
252 let old_status = std::mem::replace(&mut *status, dummy_status);
253 match old_status {
254 SignalStatus::Caught(signals) => Poll::Ready(signals),
255 SignalStatus::Expected(_) => {
256 *status = SignalStatus::Expected(Some(context.waker().clone()));
257 Poll::Pending
258 }
259 }
260 })
261 .await
262 }
263
264 pub async fn wait_for_signal(&self, signal: signal::Number) {
274 while !self.wait_for_signals().await.contains(&signal) {}
275 }
276
277 pub fn select(&self, poll: bool) -> Result<()> {
294 self.0.borrow_mut().select(poll)
295 }
296}
297
298impl System for &SharedSystem {
303 fn fstat(&self, fd: Fd) -> Result<Stat> {
304 self.0.borrow().fstat(fd)
305 }
306 fn fstatat(&self, dir_fd: Fd, path: &CStr, follow_symlinks: bool) -> Result<Stat> {
307 self.0.borrow().fstatat(dir_fd, path, follow_symlinks)
308 }
309 fn is_executable_file(&self, path: &CStr) -> bool {
310 self.0.borrow().is_executable_file(path)
311 }
312 fn is_directory(&self, path: &CStr) -> bool {
313 self.0.borrow().is_directory(path)
314 }
315 fn pipe(&mut self) -> Result<(Fd, Fd)> {
316 self.0.borrow_mut().pipe()
317 }
318 fn dup(&mut self, from: Fd, to_min: Fd, flags: EnumSet<FdFlag>) -> Result<Fd> {
319 self.0.borrow_mut().dup(from, to_min, flags)
320 }
321 fn dup2(&mut self, from: Fd, to: Fd) -> Result<Fd> {
322 self.0.borrow_mut().dup2(from, to)
323 }
324 fn open(
325 &mut self,
326 path: &CStr,
327 access: OfdAccess,
328 flags: EnumSet<OpenFlag>,
329 mode: Mode,
330 ) -> Result<Fd> {
331 self.0.borrow_mut().open(path, access, flags, mode)
332 }
333 fn open_tmpfile(&mut self, parent_dir: &Path) -> Result<Fd> {
334 self.0.borrow_mut().open_tmpfile(parent_dir)
335 }
336 fn close(&mut self, fd: Fd) -> Result<()> {
337 self.0.borrow_mut().close(fd)
338 }
339 fn ofd_access(&self, fd: Fd) -> Result<OfdAccess> {
340 self.0.borrow().ofd_access(fd)
341 }
342 fn get_and_set_nonblocking(&mut self, fd: Fd, nonblocking: bool) -> Result<bool> {
343 self.0.borrow_mut().get_and_set_nonblocking(fd, nonblocking)
344 }
345 fn fcntl_getfd(&self, fd: Fd) -> Result<EnumSet<FdFlag>> {
346 self.0.borrow().fcntl_getfd(fd)
347 }
348 fn fcntl_setfd(&mut self, fd: Fd, flags: EnumSet<FdFlag>) -> Result<()> {
349 self.0.borrow_mut().fcntl_setfd(fd, flags)
350 }
351 fn isatty(&self, fd: Fd) -> bool {
352 self.0.borrow().isatty(fd)
353 }
354 fn read(&mut self, fd: Fd, buffer: &mut [u8]) -> Result<usize> {
355 self.0.borrow_mut().read(fd, buffer)
356 }
357 fn write(&mut self, fd: Fd, buffer: &[u8]) -> Result<usize> {
358 self.0.borrow_mut().write(fd, buffer)
359 }
360 fn lseek(&mut self, fd: Fd, position: SeekFrom) -> Result<u64> {
361 self.0.borrow_mut().lseek(fd, position)
362 }
363 fn fdopendir(&mut self, fd: Fd) -> Result<Box<dyn Dir>> {
364 self.0.borrow_mut().fdopendir(fd)
365 }
366 fn opendir(&mut self, path: &CStr) -> Result<Box<dyn Dir>> {
367 self.0.borrow_mut().opendir(path)
368 }
369 fn umask(&mut self, mask: Mode) -> Mode {
370 self.0.borrow_mut().umask(mask)
371 }
372 fn now(&self) -> Instant {
373 self.0.borrow().now()
374 }
375 fn times(&self) -> Result<Times> {
376 self.0.borrow().times()
377 }
378 fn validate_signal(&self, number: signal::RawNumber) -> Option<(signal::Name, signal::Number)> {
379 self.0.borrow().validate_signal(number)
380 }
381 fn signal_number_from_name(&self, name: signal::Name) -> Option<signal::Number> {
382 self.0.borrow().signal_number_from_name(name)
383 }
384 fn sigmask(
385 &mut self,
386 op: Option<(SigmaskOp, &[signal::Number])>,
387 old_mask: Option<&mut Vec<signal::Number>>,
388 ) -> Result<()> {
389 (**self.0.borrow_mut()).sigmask(op, old_mask)
390 }
391 fn sigaction(&mut self, signal: signal::Number, action: Disposition) -> Result<Disposition> {
392 self.0.borrow_mut().sigaction(signal, action)
393 }
394 fn caught_signals(&mut self) -> Vec<signal::Number> {
395 self.0.borrow_mut().caught_signals()
396 }
397 fn kill(
398 &mut self,
399 target: Pid,
400 signal: Option<signal::Number>,
401 ) -> Pin<Box<(dyn Future<Output = Result<()>>)>> {
402 self.0.borrow_mut().kill(target, signal)
403 }
404 fn select(
405 &mut self,
406 readers: &mut Vec<Fd>,
407 writers: &mut Vec<Fd>,
408 timeout: Option<Duration>,
409 signal_mask: Option<&[signal::Number]>,
410 ) -> Result<c_int> {
411 (**self.0.borrow_mut()).select(readers, writers, timeout, signal_mask)
412 }
413 fn getpid(&self) -> Pid {
414 self.0.borrow().getpid()
415 }
416 fn getppid(&self) -> Pid {
417 self.0.borrow().getppid()
418 }
419 fn getpgrp(&self) -> Pid {
420 self.0.borrow().getpgrp()
421 }
422 fn setpgid(&mut self, pid: Pid, pgid: Pid) -> Result<()> {
423 self.0.borrow_mut().setpgid(pid, pgid)
424 }
425 fn tcgetpgrp(&self, fd: Fd) -> Result<Pid> {
426 self.0.borrow().tcgetpgrp(fd)
427 }
428 fn tcsetpgrp(&mut self, fd: Fd, pgid: Pid) -> Result<()> {
429 self.0.borrow_mut().tcsetpgrp(fd, pgid)
430 }
431 fn new_child_process(&mut self) -> Result<ChildProcessStarter> {
432 self.0.borrow_mut().new_child_process()
433 }
434 fn wait(&mut self, target: Pid) -> Result<Option<(Pid, ProcessState)>> {
435 self.0.borrow_mut().wait(target)
436 }
437 fn execve(&mut self, path: &CStr, args: &[CString], envs: &[CString]) -> Result<Infallible> {
438 self.0.borrow_mut().execve(path, args, envs)
439 }
440 fn getcwd(&self) -> Result<PathBuf> {
441 self.0.borrow().getcwd()
442 }
443 fn chdir(&mut self, path: &CStr) -> Result<()> {
444 self.0.borrow_mut().chdir(path)
445 }
446 fn getuid(&self) -> Uid {
447 self.0.borrow().getuid()
448 }
449 fn geteuid(&self) -> Uid {
450 self.0.borrow().geteuid()
451 }
452 fn getgid(&self) -> Gid {
453 self.0.borrow().getgid()
454 }
455 fn getegid(&self) -> Gid {
456 self.0.borrow().getegid()
457 }
458 fn getpwnam_dir(&self, name: &str) -> Result<Option<PathBuf>> {
459 self.0.borrow().getpwnam_dir(name)
460 }
461 fn confstr_path(&self) -> Result<UnixString> {
462 self.0.borrow().confstr_path()
463 }
464 fn shell_path(&self) -> CString {
465 self.0.borrow().shell_path()
466 }
467 fn getrlimit(&self, resource: Resource) -> Result<LimitPair> {
468 self.0.borrow().getrlimit(resource)
469 }
470 fn setrlimit(&mut self, resource: Resource, limits: LimitPair) -> Result<()> {
471 self.0.borrow_mut().setrlimit(resource, limits)
472 }
473}
474
475impl System for SharedSystem {
477 #[inline]
480 fn fstat(&self, fd: Fd) -> Result<Stat> {
481 (&self).fstat(fd)
482 }
483 #[inline]
484 fn fstatat(&self, dir_fd: Fd, path: &CStr, follow_symlinks: bool) -> Result<Stat> {
485 (&self).fstatat(dir_fd, path, follow_symlinks)
486 }
487 #[inline]
488 fn is_executable_file(&self, path: &CStr) -> bool {
489 (&self).is_executable_file(path)
490 }
491 #[inline]
492 fn is_directory(&self, path: &CStr) -> bool {
493 (&self).is_directory(path)
494 }
495 #[inline]
496 fn pipe(&mut self) -> Result<(Fd, Fd)> {
497 (&mut &*self).pipe()
498 }
499 #[inline]
500 fn dup(&mut self, from: Fd, to_min: Fd, flags: EnumSet<FdFlag>) -> Result<Fd> {
501 (&mut &*self).dup(from, to_min, flags)
502 }
503 #[inline]
504 fn dup2(&mut self, from: Fd, to: Fd) -> Result<Fd> {
505 (&mut &*self).dup2(from, to)
506 }
507 #[inline]
508 fn open(
509 &mut self,
510 path: &CStr,
511 access: OfdAccess,
512 flags: EnumSet<OpenFlag>,
513 mode: Mode,
514 ) -> Result<Fd> {
515 (&mut &*self).open(path, access, flags, mode)
516 }
517 #[inline]
518 fn open_tmpfile(&mut self, parent_dir: &Path) -> Result<Fd> {
519 (&mut &*self).open_tmpfile(parent_dir)
520 }
521 #[inline]
522 fn close(&mut self, fd: Fd) -> Result<()> {
523 (&mut &*self).close(fd)
524 }
525 #[inline]
526 fn ofd_access(&self, fd: Fd) -> Result<OfdAccess> {
527 (&self).ofd_access(fd)
528 }
529 #[inline]
530 fn get_and_set_nonblocking(&mut self, fd: Fd, nonblocking: bool) -> Result<bool> {
531 (&mut &*self).get_and_set_nonblocking(fd, nonblocking)
532 }
533 #[inline]
534 fn fcntl_getfd(&self, fd: Fd) -> Result<EnumSet<FdFlag>> {
535 (&self).fcntl_getfd(fd)
536 }
537 #[inline]
538 fn fcntl_setfd(&mut self, fd: Fd, flags: EnumSet<FdFlag>) -> Result<()> {
539 (&mut &*self).fcntl_setfd(fd, flags)
540 }
541 #[inline]
542 fn isatty(&self, fd: Fd) -> bool {
543 (&self).isatty(fd)
544 }
545 #[inline]
546 fn read(&mut self, fd: Fd, buffer: &mut [u8]) -> Result<usize> {
547 (&mut &*self).read(fd, buffer)
548 }
549 #[inline]
550 fn write(&mut self, fd: Fd, buffer: &[u8]) -> Result<usize> {
551 (&mut &*self).write(fd, buffer)
552 }
553 #[inline]
554 fn lseek(&mut self, fd: Fd, position: SeekFrom) -> Result<u64> {
555 (&mut &*self).lseek(fd, position)
556 }
557 #[inline]
558 fn fdopendir(&mut self, fd: Fd) -> Result<Box<dyn Dir>> {
559 (&mut &*self).fdopendir(fd)
560 }
561 #[inline]
562 fn opendir(&mut self, path: &CStr) -> Result<Box<dyn Dir>> {
563 (&mut &*self).opendir(path)
564 }
565 #[inline]
566 fn umask(&mut self, mask: Mode) -> Mode {
567 (&mut &*self).umask(mask)
568 }
569 #[inline]
570 fn now(&self) -> Instant {
571 (&self).now()
572 }
573 #[inline]
574 fn times(&self) -> Result<Times> {
575 (&self).times()
576 }
577 #[inline]
578 fn validate_signal(&self, number: signal::RawNumber) -> Option<(signal::Name, signal::Number)> {
579 (&self).validate_signal(number)
580 }
581 #[inline]
582 fn signal_number_from_name(&self, name: signal::Name) -> Option<signal::Number> {
583 System::signal_number_from_name(&self, name)
584 }
585 #[inline]
586 fn sigmask(
587 &mut self,
588 op: Option<(SigmaskOp, &[signal::Number])>,
589 old_mask: Option<&mut Vec<signal::Number>>,
590 ) -> Result<()> {
591 (&mut &*self).sigmask(op, old_mask)
592 }
593 #[inline]
594 fn sigaction(&mut self, signal: signal::Number, action: Disposition) -> Result<Disposition> {
595 (&mut &*self).sigaction(signal, action)
596 }
597 #[inline]
598 fn caught_signals(&mut self) -> Vec<signal::Number> {
599 (&mut &*self).caught_signals()
600 }
601 #[inline]
602 fn kill(
603 &mut self,
604 target: Pid,
605 signal: Option<signal::Number>,
606 ) -> Pin<Box<dyn Future<Output = Result<()>>>> {
607 (&mut &*self).kill(target, signal)
608 }
609 #[inline]
610 fn select(
611 &mut self,
612 readers: &mut Vec<Fd>,
613 writers: &mut Vec<Fd>,
614 timeout: Option<Duration>,
615 signal_mask: Option<&[signal::Number]>,
616 ) -> Result<c_int> {
617 (&mut &*self).select(readers, writers, timeout, signal_mask)
618 }
619 #[inline]
620 fn getpid(&self) -> Pid {
621 (&self).getpid()
622 }
623 #[inline]
624 fn getppid(&self) -> Pid {
625 (&self).getppid()
626 }
627 #[inline]
628 fn getpgrp(&self) -> Pid {
629 (&self).getpgrp()
630 }
631 #[inline]
632 fn setpgid(&mut self, pid: Pid, pgid: Pid) -> Result<()> {
633 (&mut &*self).setpgid(pid, pgid)
634 }
635 #[inline]
636 fn tcgetpgrp(&self, fd: Fd) -> Result<Pid> {
637 (&self).tcgetpgrp(fd)
638 }
639 #[inline]
640 fn tcsetpgrp(&mut self, fd: Fd, pgid: Pid) -> Result<()> {
641 (&mut &*self).tcsetpgrp(fd, pgid)
642 }
643 #[inline]
644 fn new_child_process(&mut self) -> Result<ChildProcessStarter> {
645 (&mut &*self).new_child_process()
646 }
647 #[inline]
648 fn wait(&mut self, target: Pid) -> Result<Option<(Pid, ProcessState)>> {
649 (&mut &*self).wait(target)
650 }
651 #[inline]
652 fn execve(&mut self, path: &CStr, args: &[CString], envs: &[CString]) -> Result<Infallible> {
653 (&mut &*self).execve(path, args, envs)
654 }
655 #[inline]
656 fn getcwd(&self) -> Result<PathBuf> {
657 (&self).getcwd()
658 }
659 #[inline]
660 fn chdir(&mut self, path: &CStr) -> Result<()> {
661 (&mut &*self).chdir(path)
662 }
663 #[inline]
664 fn getuid(&self) -> Uid {
665 (&self).getuid()
666 }
667 #[inline]
668 fn geteuid(&self) -> Uid {
669 (&self).geteuid()
670 }
671 #[inline]
672 fn getgid(&self) -> Gid {
673 (&self).getgid()
674 }
675 #[inline]
676 fn getegid(&self) -> Gid {
677 (&self).getegid()
678 }
679 #[inline]
680 fn getpwnam_dir(&self, name: &str) -> Result<Option<PathBuf>> {
681 (&self).getpwnam_dir(name)
682 }
683 #[inline]
684 fn confstr_path(&self) -> Result<UnixString> {
685 (&self).confstr_path()
686 }
687 #[inline]
688 fn shell_path(&self) -> CString {
689 (&self).shell_path()
690 }
691 #[inline]
692 fn getrlimit(&self, resource: Resource) -> Result<LimitPair> {
693 (&self).getrlimit(resource)
694 }
695 #[inline]
696 fn setrlimit(&mut self, resource: Resource, limits: LimitPair) -> Result<()> {
697 (&mut &*self).setrlimit(resource, limits)
698 }
699}
700
701impl SignalSystem for &SharedSystem {
702 #[inline]
703 fn signal_name_from_number(&self, number: signal::Number) -> signal::Name {
704 SystemEx::signal_name_from_number(*self, number)
705 }
706
707 #[inline]
708 fn signal_number_from_name(&self, name: signal::Name) -> Option<signal::Number> {
709 System::signal_number_from_name(*self, name)
710 }
711
712 fn set_disposition(
713 &mut self,
714 signal: signal::Number,
715 disposition: Disposition,
716 ) -> Result<Disposition> {
717 self.0.borrow_mut().set_disposition(signal, disposition)
718 }
719}
720
721impl SignalSystem for SharedSystem {
722 #[inline]
723 fn signal_name_from_number(&self, number: signal::Number) -> signal::Name {
724 SystemEx::signal_name_from_number(self, number)
725 }
726
727 #[inline]
728 fn signal_number_from_name(&self, name: signal::Name) -> Option<signal::Number> {
729 System::signal_number_from_name(self, name)
730 }
731
732 #[inline]
733 fn set_disposition(
734 &mut self,
735 signal: signal::Number,
736 disposition: Disposition,
737 ) -> Result<Disposition> {
738 self.0.borrow_mut().set_disposition(signal, disposition)
739 }
740}
741
742#[cfg(test)]
743mod tests {
744 use super::super::r#virtual::VirtualSystem;
745 use super::super::r#virtual::PIPE_SIZE;
746 use super::super::r#virtual::{SIGCHLD, SIGINT, SIGTERM, SIGUSR1};
747 use super::*;
748 use assert_matches::assert_matches;
749 use futures_util::task::noop_waker_ref;
750 use futures_util::FutureExt as _;
751 use std::task::Context;
752 use std::task::Poll;
753 use std::time::Duration;
754
755 #[test]
756 fn shared_system_read_async_ready() {
757 let mut system = SharedSystem::new(Box::new(VirtualSystem::new()));
758 let (reader, writer) = system.pipe().unwrap();
759 system.write(writer, &[42]).unwrap();
760
761 let mut buffer = [0; 2];
762 let result = system.read_async(reader, &mut buffer).now_or_never();
763 assert_eq!(result, Some(Ok(1)));
764 assert_eq!(buffer[..1], [42]);
765 }
766
767 #[test]
768 fn shared_system_read_async_not_ready_at_first() {
769 let system = VirtualSystem::new();
770 let process_id = system.process_id;
771 let state = Rc::clone(&system.state);
772 let mut system = SharedSystem::new(Box::new(system));
773 let system2 = system.clone();
774 let (reader, writer) = system.pipe().unwrap();
775
776 let mut context = Context::from_waker(noop_waker_ref());
777 let mut buffer = [0; 2];
778 let mut future = Box::pin(system.read_async(reader, &mut buffer));
779 let result = future.as_mut().poll(&mut context);
780 assert_eq!(result, Poll::Pending);
781
782 let result = system2.select(false);
783 assert_eq!(result, Ok(()));
784 let result = future.as_mut().poll(&mut context);
785 assert_eq!(result, Poll::Pending);
786
787 state.borrow_mut().processes[&process_id].fds[&writer]
788 .open_file_description
789 .borrow_mut()
790 .write(&[56])
791 .unwrap();
792
793 let result = future.as_mut().poll(&mut context);
794 drop(future);
795 assert_eq!(result, Poll::Ready(Ok(1)));
796 assert_eq!(buffer[..1], [56]);
797 }
798
799 #[test]
800 fn shared_system_write_all_ready() {
801 let mut system = SharedSystem::new(Box::new(VirtualSystem::new()));
802 let (reader, writer) = system.pipe().unwrap();
803 let result = system.write_all(writer, &[17]).now_or_never().unwrap();
804 assert_eq!(result, Ok(1));
805
806 let mut buffer = [0; 2];
807 system.read(reader, &mut buffer).unwrap();
808 assert_eq!(buffer[..1], [17]);
809 }
810
811 #[test]
812 fn shared_system_write_all_not_ready_at_first() {
813 let system = VirtualSystem::new();
814 let process_id = system.process_id;
815 let state = Rc::clone(&system.state);
816 let mut system = SharedSystem::new(Box::new(system));
817 let (reader, writer) = system.pipe().unwrap();
818
819 state.borrow_mut().processes[&process_id].fds[&writer]
820 .open_file_description
821 .borrow_mut()
822 .write(&[42; PIPE_SIZE])
823 .unwrap();
824
825 let mut context = Context::from_waker(noop_waker_ref());
826 let mut out_buffer = [87; PIPE_SIZE];
827 out_buffer[0] = 0;
828 out_buffer[1] = 1;
829 out_buffer[PIPE_SIZE - 2] = 0xFE;
830 out_buffer[PIPE_SIZE - 1] = 0xFF;
831 let mut future = Box::pin(system.write_all(writer, &out_buffer));
832 let result = future.as_mut().poll(&mut context);
833 assert_eq!(result, Poll::Pending);
834
835 let mut in_buffer = [0; PIPE_SIZE - 1];
836 state.borrow_mut().processes[&process_id].fds[&reader]
837 .open_file_description
838 .borrow_mut()
839 .read(&mut in_buffer)
840 .unwrap();
841 assert_eq!(in_buffer, [42; PIPE_SIZE - 1]);
842
843 let result = future.as_mut().poll(&mut context);
844 assert_eq!(result, Poll::Pending);
845
846 in_buffer[0] = 0;
847 state.borrow_mut().processes[&process_id].fds[&reader]
848 .open_file_description
849 .borrow_mut()
850 .read(&mut in_buffer[..1])
851 .unwrap();
852 assert_eq!(in_buffer[..1], [42; 1]);
853
854 let result = future.as_mut().poll(&mut context);
855 assert_eq!(result, Poll::Ready(Ok(out_buffer.len())));
856
857 state.borrow_mut().processes[&process_id].fds[&reader]
858 .open_file_description
859 .borrow_mut()
860 .read(&mut in_buffer)
861 .unwrap();
862 assert_eq!(in_buffer, out_buffer[..PIPE_SIZE - 1]);
863 state.borrow_mut().processes[&process_id].fds[&reader]
864 .open_file_description
865 .borrow_mut()
866 .read(&mut in_buffer)
867 .unwrap();
868 assert_eq!(in_buffer[..1], out_buffer[PIPE_SIZE - 1..]);
869 }
870
871 #[test]
872 fn shared_system_write_all_empty() {
873 let system = VirtualSystem::new();
874 let process_id = system.process_id;
875 let state = Rc::clone(&system.state);
876 let mut system = SharedSystem::new(Box::new(system));
877 let (_reader, writer) = system.pipe().unwrap();
878
879 state.borrow_mut().processes[&process_id].fds[&writer]
880 .open_file_description
881 .borrow_mut()
882 .write(&[0; PIPE_SIZE])
883 .unwrap();
884
885 let mut context = Context::from_waker(noop_waker_ref());
887 let mut future = Box::pin(system.write_all(writer, &[]));
888 let result = future.as_mut().poll(&mut context);
889 assert_eq!(result, Poll::Ready(Ok(0)));
890 }
892
893 #[test]
896 fn shared_system_wait_until() {
897 let system = VirtualSystem::new();
898 let state = Rc::clone(&system.state);
899 let system = SharedSystem::new(Box::new(system));
900 let start = Instant::now();
901 state.borrow_mut().now = Some(start);
902 let target = start + Duration::from_millis(1_125);
903
904 let mut future = Box::pin(system.wait_until(target));
905 let mut context = Context::from_waker(noop_waker_ref());
906 let poll = future.as_mut().poll(&mut context);
907 assert_eq!(poll, Poll::Pending);
908
909 system.select(false).unwrap();
910 let poll = future.as_mut().poll(&mut context);
911 assert_eq!(poll, Poll::Ready(()));
912 assert_eq!(state.borrow().now, Some(target));
913 }
914
915 #[test]
916 fn shared_system_wait_for_signals() {
917 let system = VirtualSystem::new();
918 let process_id = system.process_id;
919 let state = Rc::clone(&system.state);
920 let mut system = SharedSystem::new(Box::new(system));
921 system.set_disposition(SIGCHLD, Disposition::Catch).unwrap();
922 system.set_disposition(SIGINT, Disposition::Catch).unwrap();
923 system.set_disposition(SIGUSR1, Disposition::Catch).unwrap();
924
925 let mut context = Context::from_waker(noop_waker_ref());
926 let mut future = Box::pin(system.wait_for_signals());
927 let result = future.as_mut().poll(&mut context);
928 assert_eq!(result, Poll::Pending);
929
930 {
931 let mut state = state.borrow_mut();
932 let process = state.processes.get_mut(&process_id).unwrap();
933 assert!(process.blocked_signals().contains(&SIGCHLD));
934 assert!(process.blocked_signals().contains(&SIGINT));
935 assert!(process.blocked_signals().contains(&SIGUSR1));
936 let _ = process.raise_signal(SIGCHLD);
937 let _ = process.raise_signal(SIGINT);
938 }
939 let result = future.as_mut().poll(&mut context);
940 assert_eq!(result, Poll::Pending);
941
942 system.select(false).unwrap();
943 let result = future.as_mut().poll(&mut context);
944 assert_matches!(result, Poll::Ready(signals) => {
945 assert_eq!(signals.len(), 2);
946 assert!(signals.contains(&SIGCHLD));
947 assert!(signals.contains(&SIGINT));
948 });
949 }
950
951 #[test]
952 fn shared_system_wait_for_signal_returns_on_caught() {
953 let system = VirtualSystem::new();
954 let process_id = system.process_id;
955 let state = Rc::clone(&system.state);
956 let mut system = SharedSystem::new(Box::new(system));
957 system.set_disposition(SIGCHLD, Disposition::Catch).unwrap();
958
959 let mut context = Context::from_waker(noop_waker_ref());
960 let mut future = Box::pin(system.wait_for_signal(SIGCHLD));
961 let result = future.as_mut().poll(&mut context);
962 assert_eq!(result, Poll::Pending);
963
964 {
965 let mut state = state.borrow_mut();
966 let process = state.processes.get_mut(&process_id).unwrap();
967 assert!(process.blocked_signals().contains(&SIGCHLD));
968 let _ = process.raise_signal(SIGCHLD);
969 }
970 let result = future.as_mut().poll(&mut context);
971 assert_eq!(result, Poll::Pending);
972
973 system.select(false).unwrap();
974 let result = future.as_mut().poll(&mut context);
975 assert_eq!(result, Poll::Ready(()));
976 }
977
978 #[test]
979 fn shared_system_wait_for_signal_ignores_irrelevant_signals() {
980 let system = VirtualSystem::new();
981 let process_id = system.process_id;
982 let state = Rc::clone(&system.state);
983 let mut system = SharedSystem::new(Box::new(system));
984 system.set_disposition(SIGINT, Disposition::Catch).unwrap();
985 system.set_disposition(SIGTERM, Disposition::Catch).unwrap();
986
987 let mut context = Context::from_waker(noop_waker_ref());
988 let mut future = Box::pin(system.wait_for_signal(SIGINT));
989 let result = future.as_mut().poll(&mut context);
990 assert_eq!(result, Poll::Pending);
991
992 {
993 let mut state = state.borrow_mut();
994 let process = state.processes.get_mut(&process_id).unwrap();
995 let _ = process.raise_signal(SIGCHLD);
996 let _ = process.raise_signal(SIGTERM);
997 }
998 system.select(false).unwrap();
999
1000 let result = future.as_mut().poll(&mut context);
1001 assert_eq!(result, Poll::Pending);
1002 }
1003
1004 #[test]
1005 fn shared_system_select_consumes_all_pending_signals() {
1006 let system = VirtualSystem::new();
1007 let process_id = system.process_id;
1008 let state = Rc::clone(&system.state);
1009 let mut system = SharedSystem::new(Box::new(system));
1010 system.set_disposition(SIGINT, Disposition::Catch).unwrap();
1011 system.set_disposition(SIGTERM, Disposition::Catch).unwrap();
1012
1013 {
1014 let mut state = state.borrow_mut();
1015 let process = state.processes.get_mut(&process_id).unwrap();
1016 let _ = process.raise_signal(SIGINT);
1017 let _ = process.raise_signal(SIGTERM);
1018 }
1019 system.select(false).unwrap();
1020
1021 let state = state.borrow();
1022 let process = state.processes.get(&process_id).unwrap();
1023 let blocked = process.blocked_signals();
1024 assert!(blocked.contains(&SIGINT));
1025 assert!(blocked.contains(&SIGTERM));
1026 let pending = process.pending_signals();
1027 assert!(!pending.contains(&SIGINT));
1028 assert!(!pending.contains(&SIGTERM));
1029 }
1030
1031 #[test]
1032 fn shared_system_select_does_not_wake_signal_waiters_on_io() {
1033 let system = VirtualSystem::new();
1034 let mut system_1 = SharedSystem::new(Box::new(system));
1035 let mut system_2 = system_1.clone();
1036 let mut system_3 = system_1.clone();
1037 let (reader, writer) = system_1.pipe().unwrap();
1038 system_2
1039 .set_disposition(SIGCHLD, Disposition::Catch)
1040 .unwrap();
1041
1042 let mut buffer = [0];
1043 let mut read_future = Box::pin(system_1.read_async(reader, &mut buffer));
1044 let mut signal_future = Box::pin(system_2.wait_for_signals());
1045 let mut context = Context::from_waker(noop_waker_ref());
1046 let result = read_future.as_mut().poll(&mut context);
1047 assert_eq!(result, Poll::Pending);
1048 let result = signal_future.as_mut().poll(&mut context);
1049 assert_eq!(result, Poll::Pending);
1050 system_3.write(writer, &[42]).unwrap();
1051 system_3.select(false).unwrap();
1052
1053 let result = read_future.as_mut().poll(&mut context);
1054 assert_eq!(result, Poll::Ready(Ok(1)));
1055 let result = signal_future.as_mut().poll(&mut context);
1056 assert_eq!(result, Poll::Pending);
1057 }
1058
1059 #[test]
1060 fn shared_system_select_poll() {
1061 let system = VirtualSystem::new();
1062 let state = Rc::clone(&system.state);
1063 let system = SharedSystem::new(Box::new(system));
1064 let start = Instant::now();
1065 state.borrow_mut().now = Some(start);
1066 let target = start + Duration::from_millis(1_125);
1067
1068 let mut future = Box::pin(system.wait_until(target));
1069 let mut context = Context::from_waker(noop_waker_ref());
1070 let poll = future.as_mut().poll(&mut context);
1071 assert_eq!(poll, Poll::Pending);
1072
1073 system.select(true).unwrap();
1074 let poll = future.as_mut().poll(&mut context);
1075 assert_eq!(poll, Poll::Pending);
1076 assert_eq!(state.borrow().now, Some(start));
1077 }
1078}