1use super::ChildProcessStarter;
20use super::Dir;
21use super::Disposition;
22use super::Errno;
23use super::FdFlag;
24use super::FlexFuture;
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 super::signal;
45#[cfg(doc)]
46use crate::Env;
47use crate::io::Fd;
48use crate::job::Pid;
49use crate::job::ProcessState;
50use crate::semantics::ExitStatus;
51use enumset::EnumSet;
52use std::cell::RefCell;
53use std::convert::Infallible;
54use std::ffi::CStr;
55use std::ffi::CString;
56use std::ffi::c_int;
57use std::future::poll_fn;
58use std::io::SeekFrom;
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 get_sigaction(&self, signal: signal::Number) -> Result<Disposition> {
392 self.0.borrow().get_sigaction(signal)
393 }
394 fn sigaction(&mut self, signal: signal::Number, action: Disposition) -> Result<Disposition> {
395 self.0.borrow_mut().sigaction(signal, action)
396 }
397 fn caught_signals(&mut self) -> Vec<signal::Number> {
398 self.0.borrow_mut().caught_signals()
399 }
400 fn kill(&mut self, target: Pid, signal: Option<signal::Number>) -> FlexFuture<Result<()>> {
401 self.0.borrow_mut().kill(target, signal)
402 }
403 fn raise(&mut self, signal: signal::Number) -> FlexFuture<Result<()>> {
404 self.0.borrow_mut().raise(signal)
405 }
406 fn select(
407 &mut self,
408 readers: &mut Vec<Fd>,
409 writers: &mut Vec<Fd>,
410 timeout: Option<Duration>,
411 signal_mask: Option<&[signal::Number]>,
412 ) -> Result<c_int> {
413 (**self.0.borrow_mut()).select(readers, writers, timeout, signal_mask)
414 }
415 fn getsid(&self, pid: Pid) -> Result<Pid> {
416 self.0.borrow().getsid(pid)
417 }
418 fn getpid(&self) -> Pid {
419 self.0.borrow().getpid()
420 }
421 fn getppid(&self) -> Pid {
422 self.0.borrow().getppid()
423 }
424 fn getpgrp(&self) -> Pid {
425 self.0.borrow().getpgrp()
426 }
427 fn setpgid(&mut self, pid: Pid, pgid: Pid) -> Result<()> {
428 self.0.borrow_mut().setpgid(pid, pgid)
429 }
430 fn tcgetpgrp(&self, fd: Fd) -> Result<Pid> {
431 self.0.borrow().tcgetpgrp(fd)
432 }
433 fn tcsetpgrp(&mut self, fd: Fd, pgid: Pid) -> Result<()> {
434 self.0.borrow_mut().tcsetpgrp(fd, pgid)
435 }
436 fn new_child_process(&mut self) -> Result<ChildProcessStarter> {
437 self.0.borrow_mut().new_child_process()
438 }
439 fn wait(&mut self, target: Pid) -> Result<Option<(Pid, ProcessState)>> {
440 self.0.borrow_mut().wait(target)
441 }
442 fn execve(
443 &mut self,
444 path: &CStr,
445 args: &[CString],
446 envs: &[CString],
447 ) -> FlexFuture<Result<Infallible>> {
448 self.0.borrow_mut().execve(path, args, envs)
449 }
450 fn exit(&mut self, exit_status: ExitStatus) -> FlexFuture<Infallible> {
451 self.0.borrow_mut().exit(exit_status)
452 }
453 fn getcwd(&self) -> Result<PathBuf> {
454 self.0.borrow().getcwd()
455 }
456 fn chdir(&mut self, path: &CStr) -> Result<()> {
457 self.0.borrow_mut().chdir(path)
458 }
459 fn getuid(&self) -> Uid {
460 self.0.borrow().getuid()
461 }
462 fn geteuid(&self) -> Uid {
463 self.0.borrow().geteuid()
464 }
465 fn getgid(&self) -> Gid {
466 self.0.borrow().getgid()
467 }
468 fn getegid(&self) -> Gid {
469 self.0.borrow().getegid()
470 }
471 fn getpwnam_dir(&self, name: &CStr) -> Result<Option<PathBuf>> {
472 self.0.borrow().getpwnam_dir(name)
473 }
474 fn confstr_path(&self) -> Result<UnixString> {
475 self.0.borrow().confstr_path()
476 }
477 fn shell_path(&self) -> CString {
478 self.0.borrow().shell_path()
479 }
480 fn getrlimit(&self, resource: Resource) -> Result<LimitPair> {
481 self.0.borrow().getrlimit(resource)
482 }
483 fn setrlimit(&mut self, resource: Resource, limits: LimitPair) -> Result<()> {
484 self.0.borrow_mut().setrlimit(resource, limits)
485 }
486}
487
488impl System for SharedSystem {
490 #[inline]
493 fn fstat(&self, fd: Fd) -> Result<Stat> {
494 (&self).fstat(fd)
495 }
496 #[inline]
497 fn fstatat(&self, dir_fd: Fd, path: &CStr, follow_symlinks: bool) -> Result<Stat> {
498 (&self).fstatat(dir_fd, path, follow_symlinks)
499 }
500 #[inline]
501 fn is_executable_file(&self, path: &CStr) -> bool {
502 (&self).is_executable_file(path)
503 }
504 #[inline]
505 fn is_directory(&self, path: &CStr) -> bool {
506 (&self).is_directory(path)
507 }
508 #[inline]
509 fn pipe(&mut self) -> Result<(Fd, Fd)> {
510 (&mut &*self).pipe()
511 }
512 #[inline]
513 fn dup(&mut self, from: Fd, to_min: Fd, flags: EnumSet<FdFlag>) -> Result<Fd> {
514 (&mut &*self).dup(from, to_min, flags)
515 }
516 #[inline]
517 fn dup2(&mut self, from: Fd, to: Fd) -> Result<Fd> {
518 (&mut &*self).dup2(from, to)
519 }
520 #[inline]
521 fn open(
522 &mut self,
523 path: &CStr,
524 access: OfdAccess,
525 flags: EnumSet<OpenFlag>,
526 mode: Mode,
527 ) -> Result<Fd> {
528 (&mut &*self).open(path, access, flags, mode)
529 }
530 #[inline]
531 fn open_tmpfile(&mut self, parent_dir: &Path) -> Result<Fd> {
532 (&mut &*self).open_tmpfile(parent_dir)
533 }
534 #[inline]
535 fn close(&mut self, fd: Fd) -> Result<()> {
536 (&mut &*self).close(fd)
537 }
538 #[inline]
539 fn ofd_access(&self, fd: Fd) -> Result<OfdAccess> {
540 (&self).ofd_access(fd)
541 }
542 #[inline]
543 fn get_and_set_nonblocking(&mut self, fd: Fd, nonblocking: bool) -> Result<bool> {
544 (&mut &*self).get_and_set_nonblocking(fd, nonblocking)
545 }
546 #[inline]
547 fn fcntl_getfd(&self, fd: Fd) -> Result<EnumSet<FdFlag>> {
548 (&self).fcntl_getfd(fd)
549 }
550 #[inline]
551 fn fcntl_setfd(&mut self, fd: Fd, flags: EnumSet<FdFlag>) -> Result<()> {
552 (&mut &*self).fcntl_setfd(fd, flags)
553 }
554 #[inline]
555 fn isatty(&self, fd: Fd) -> bool {
556 (&self).isatty(fd)
557 }
558 #[inline]
559 fn read(&mut self, fd: Fd, buffer: &mut [u8]) -> Result<usize> {
560 (&mut &*self).read(fd, buffer)
561 }
562 #[inline]
563 fn write(&mut self, fd: Fd, buffer: &[u8]) -> Result<usize> {
564 (&mut &*self).write(fd, buffer)
565 }
566 #[inline]
567 fn lseek(&mut self, fd: Fd, position: SeekFrom) -> Result<u64> {
568 (&mut &*self).lseek(fd, position)
569 }
570 #[inline]
571 fn fdopendir(&mut self, fd: Fd) -> Result<Box<dyn Dir>> {
572 (&mut &*self).fdopendir(fd)
573 }
574 #[inline]
575 fn opendir(&mut self, path: &CStr) -> Result<Box<dyn Dir>> {
576 (&mut &*self).opendir(path)
577 }
578 #[inline]
579 fn umask(&mut self, mask: Mode) -> Mode {
580 (&mut &*self).umask(mask)
581 }
582 #[inline]
583 fn now(&self) -> Instant {
584 (&self).now()
585 }
586 #[inline]
587 fn times(&self) -> Result<Times> {
588 (&self).times()
589 }
590 #[inline]
591 fn validate_signal(&self, number: signal::RawNumber) -> Option<(signal::Name, signal::Number)> {
592 (&self).validate_signal(number)
593 }
594 #[inline]
595 fn signal_number_from_name(&self, name: signal::Name) -> Option<signal::Number> {
596 System::signal_number_from_name(&self, name)
597 }
598 #[inline]
599 fn sigmask(
600 &mut self,
601 op: Option<(SigmaskOp, &[signal::Number])>,
602 old_mask: Option<&mut Vec<signal::Number>>,
603 ) -> Result<()> {
604 (&mut &*self).sigmask(op, old_mask)
605 }
606 #[inline]
607 fn get_sigaction(&self, signal: signal::Number) -> Result<Disposition> {
608 (&self).get_sigaction(signal)
609 }
610 #[inline]
611 fn sigaction(&mut self, signal: signal::Number, action: Disposition) -> Result<Disposition> {
612 (&mut &*self).sigaction(signal, action)
613 }
614 #[inline]
615 fn caught_signals(&mut self) -> Vec<signal::Number> {
616 (&mut &*self).caught_signals()
617 }
618 #[inline]
619 fn kill(&mut self, target: Pid, signal: Option<signal::Number>) -> FlexFuture<Result<()>> {
620 (&mut &*self).kill(target, signal)
621 }
622 #[inline]
623 fn raise(&mut self, signal: signal::Number) -> FlexFuture<Result<()>> {
624 (&mut &*self).raise(signal)
625 }
626 #[inline]
627 fn select(
628 &mut self,
629 readers: &mut Vec<Fd>,
630 writers: &mut Vec<Fd>,
631 timeout: Option<Duration>,
632 signal_mask: Option<&[signal::Number]>,
633 ) -> Result<c_int> {
634 (&mut &*self).select(readers, writers, timeout, signal_mask)
635 }
636 #[inline]
637 fn getsid(&self, pid: Pid) -> Result<Pid> {
638 (&self).getsid(pid)
639 }
640 #[inline]
641 fn getpid(&self) -> Pid {
642 (&self).getpid()
643 }
644 #[inline]
645 fn getppid(&self) -> Pid {
646 (&self).getppid()
647 }
648 #[inline]
649 fn getpgrp(&self) -> Pid {
650 (&self).getpgrp()
651 }
652 #[inline]
653 fn setpgid(&mut self, pid: Pid, pgid: Pid) -> Result<()> {
654 (&mut &*self).setpgid(pid, pgid)
655 }
656 #[inline]
657 fn tcgetpgrp(&self, fd: Fd) -> Result<Pid> {
658 (&self).tcgetpgrp(fd)
659 }
660 #[inline]
661 fn tcsetpgrp(&mut self, fd: Fd, pgid: Pid) -> Result<()> {
662 (&mut &*self).tcsetpgrp(fd, pgid)
663 }
664 #[inline]
665 fn new_child_process(&mut self) -> Result<ChildProcessStarter> {
666 (&mut &*self).new_child_process()
667 }
668 #[inline]
669 fn wait(&mut self, target: Pid) -> Result<Option<(Pid, ProcessState)>> {
670 (&mut &*self).wait(target)
671 }
672 #[inline]
673 fn execve(
674 &mut self,
675 path: &CStr,
676 args: &[CString],
677 envs: &[CString],
678 ) -> FlexFuture<Result<Infallible>> {
679 (&mut &*self).execve(path, args, envs)
680 }
681 #[inline]
682 fn exit(&mut self, exit_status: ExitStatus) -> FlexFuture<Infallible> {
683 (&mut &*self).exit(exit_status)
684 }
685 #[inline]
686 fn getcwd(&self) -> Result<PathBuf> {
687 (&self).getcwd()
688 }
689 #[inline]
690 fn chdir(&mut self, path: &CStr) -> Result<()> {
691 (&mut &*self).chdir(path)
692 }
693 #[inline]
694 fn getuid(&self) -> Uid {
695 (&self).getuid()
696 }
697 #[inline]
698 fn geteuid(&self) -> Uid {
699 (&self).geteuid()
700 }
701 #[inline]
702 fn getgid(&self) -> Gid {
703 (&self).getgid()
704 }
705 #[inline]
706 fn getegid(&self) -> Gid {
707 (&self).getegid()
708 }
709 #[inline]
710 fn getpwnam_dir(&self, name: &CStr) -> Result<Option<PathBuf>> {
711 (&self).getpwnam_dir(name)
712 }
713 #[inline]
714 fn confstr_path(&self) -> Result<UnixString> {
715 (&self).confstr_path()
716 }
717 #[inline]
718 fn shell_path(&self) -> CString {
719 (&self).shell_path()
720 }
721 #[inline]
722 fn getrlimit(&self, resource: Resource) -> Result<LimitPair> {
723 (&self).getrlimit(resource)
724 }
725 #[inline]
726 fn setrlimit(&mut self, resource: Resource, limits: LimitPair) -> Result<()> {
727 (&mut &*self).setrlimit(resource, limits)
728 }
729}
730
731impl SignalSystem for &SharedSystem {
732 #[inline]
733 fn signal_name_from_number(&self, number: signal::Number) -> signal::Name {
734 SystemEx::signal_name_from_number(*self, number)
735 }
736
737 #[inline]
738 fn signal_number_from_name(&self, name: signal::Name) -> Option<signal::Number> {
739 System::signal_number_from_name(*self, name)
740 }
741
742 fn get_disposition(&self, signal: signal::Number) -> Result<Disposition> {
743 self.0.borrow().get_disposition(signal)
744 }
745
746 fn set_disposition(
747 &mut self,
748 signal: signal::Number,
749 disposition: Disposition,
750 ) -> Result<Disposition> {
751 self.0.borrow_mut().set_disposition(signal, disposition)
752 }
753}
754
755impl SignalSystem for SharedSystem {
756 #[inline]
757 fn signal_name_from_number(&self, number: signal::Number) -> signal::Name {
758 SystemEx::signal_name_from_number(self, number)
759 }
760
761 #[inline]
762 fn signal_number_from_name(&self, name: signal::Name) -> Option<signal::Number> {
763 System::signal_number_from_name(self, name)
764 }
765
766 #[inline]
767 fn get_disposition(&self, signal: signal::Number) -> Result<Disposition> {
768 self.0.borrow().get_disposition(signal)
769 }
770
771 #[inline]
772 fn set_disposition(
773 &mut self,
774 signal: signal::Number,
775 disposition: Disposition,
776 ) -> Result<Disposition> {
777 self.0.borrow_mut().set_disposition(signal, disposition)
778 }
779}
780
781#[cfg(test)]
782mod tests {
783 use super::super::r#virtual::PIPE_SIZE;
784 use super::super::r#virtual::VirtualSystem;
785 use super::super::r#virtual::{SIGCHLD, SIGINT, SIGTERM, SIGUSR1};
786 use super::*;
787 use assert_matches::assert_matches;
788 use futures_util::FutureExt as _;
789 use std::task::Context;
790 use std::task::Poll;
791 use std::task::Waker;
792 use std::time::Duration;
793
794 #[test]
795 fn shared_system_read_async_ready() {
796 let mut system = SharedSystem::new(Box::new(VirtualSystem::new()));
797 let (reader, writer) = system.pipe().unwrap();
798 system.write(writer, &[42]).unwrap();
799
800 let mut buffer = [0; 2];
801 let result = system.read_async(reader, &mut buffer).now_or_never();
802 assert_eq!(result, Some(Ok(1)));
803 assert_eq!(buffer[..1], [42]);
804 }
805
806 #[test]
807 fn shared_system_read_async_not_ready_at_first() {
808 let system = VirtualSystem::new();
809 let process_id = system.process_id;
810 let state = Rc::clone(&system.state);
811 let mut system = SharedSystem::new(Box::new(system));
812 let system2 = system.clone();
813 let (reader, writer) = system.pipe().unwrap();
814
815 let mut context = Context::from_waker(Waker::noop());
816 let mut buffer = [0; 2];
817 let mut future = Box::pin(system.read_async(reader, &mut buffer));
818 let result = future.as_mut().poll(&mut context);
819 assert_eq!(result, Poll::Pending);
820
821 let result = system2.select(false);
822 assert_eq!(result, Ok(()));
823 let result = future.as_mut().poll(&mut context);
824 assert_eq!(result, Poll::Pending);
825
826 state.borrow_mut().processes[&process_id].fds[&writer]
827 .open_file_description
828 .borrow_mut()
829 .write(&[56])
830 .unwrap();
831
832 let result = future.as_mut().poll(&mut context);
833 drop(future);
834 assert_eq!(result, Poll::Ready(Ok(1)));
835 assert_eq!(buffer[..1], [56]);
836 }
837
838 #[test]
839 fn shared_system_write_all_ready() {
840 let mut system = SharedSystem::new(Box::new(VirtualSystem::new()));
841 let (reader, writer) = system.pipe().unwrap();
842 let result = system.write_all(writer, &[17]).now_or_never().unwrap();
843 assert_eq!(result, Ok(1));
844
845 let mut buffer = [0; 2];
846 system.read(reader, &mut buffer).unwrap();
847 assert_eq!(buffer[..1], [17]);
848 }
849
850 #[test]
851 fn shared_system_write_all_not_ready_at_first() {
852 let system = VirtualSystem::new();
853 let process_id = system.process_id;
854 let state = Rc::clone(&system.state);
855 let mut system = SharedSystem::new(Box::new(system));
856 let (reader, writer) = system.pipe().unwrap();
857
858 state.borrow_mut().processes[&process_id].fds[&writer]
859 .open_file_description
860 .borrow_mut()
861 .write(&[42; PIPE_SIZE])
862 .unwrap();
863
864 let mut context = Context::from_waker(Waker::noop());
865 let mut out_buffer = [87; PIPE_SIZE];
866 out_buffer[0] = 0;
867 out_buffer[1] = 1;
868 out_buffer[PIPE_SIZE - 2] = 0xFE;
869 out_buffer[PIPE_SIZE - 1] = 0xFF;
870 let mut future = Box::pin(system.write_all(writer, &out_buffer));
871 let result = future.as_mut().poll(&mut context);
872 assert_eq!(result, Poll::Pending);
873
874 let mut in_buffer = [0; PIPE_SIZE - 1];
875 state.borrow_mut().processes[&process_id].fds[&reader]
876 .open_file_description
877 .borrow_mut()
878 .read(&mut in_buffer)
879 .unwrap();
880 assert_eq!(in_buffer, [42; PIPE_SIZE - 1]);
881
882 let result = future.as_mut().poll(&mut context);
883 assert_eq!(result, Poll::Pending);
884
885 in_buffer[0] = 0;
886 state.borrow_mut().processes[&process_id].fds[&reader]
887 .open_file_description
888 .borrow_mut()
889 .read(&mut in_buffer[..1])
890 .unwrap();
891 assert_eq!(in_buffer[..1], [42; 1]);
892
893 let result = future.as_mut().poll(&mut context);
894 assert_eq!(result, Poll::Ready(Ok(out_buffer.len())));
895
896 state.borrow_mut().processes[&process_id].fds[&reader]
897 .open_file_description
898 .borrow_mut()
899 .read(&mut in_buffer)
900 .unwrap();
901 assert_eq!(in_buffer, out_buffer[..PIPE_SIZE - 1]);
902 state.borrow_mut().processes[&process_id].fds[&reader]
903 .open_file_description
904 .borrow_mut()
905 .read(&mut in_buffer)
906 .unwrap();
907 assert_eq!(in_buffer[..1], out_buffer[PIPE_SIZE - 1..]);
908 }
909
910 #[test]
911 fn shared_system_write_all_empty() {
912 let system = VirtualSystem::new();
913 let process_id = system.process_id;
914 let state = Rc::clone(&system.state);
915 let mut system = SharedSystem::new(Box::new(system));
916 let (_reader, writer) = system.pipe().unwrap();
917
918 state.borrow_mut().processes[&process_id].fds[&writer]
919 .open_file_description
920 .borrow_mut()
921 .write(&[0; PIPE_SIZE])
922 .unwrap();
923
924 let mut context = Context::from_waker(Waker::noop());
926 let mut future = Box::pin(system.write_all(writer, &[]));
927 let result = future.as_mut().poll(&mut context);
928 assert_eq!(result, Poll::Ready(Ok(0)));
929 }
931
932 #[test]
935 fn shared_system_wait_until() {
936 let system = VirtualSystem::new();
937 let state = Rc::clone(&system.state);
938 let system = SharedSystem::new(Box::new(system));
939 let start = Instant::now();
940 state.borrow_mut().now = Some(start);
941 let target = start + Duration::from_millis(1_125);
942
943 let mut future = Box::pin(system.wait_until(target));
944 let mut context = Context::from_waker(Waker::noop());
945 let poll = future.as_mut().poll(&mut context);
946 assert_eq!(poll, Poll::Pending);
947
948 system.select(false).unwrap();
949 let poll = future.as_mut().poll(&mut context);
950 assert_eq!(poll, Poll::Ready(()));
951 assert_eq!(state.borrow().now, Some(target));
952 }
953
954 #[test]
955 fn shared_system_wait_for_signals() {
956 let system = VirtualSystem::new();
957 let process_id = system.process_id;
958 let state = Rc::clone(&system.state);
959 let mut system = SharedSystem::new(Box::new(system));
960 system.set_disposition(SIGCHLD, Disposition::Catch).unwrap();
961 system.set_disposition(SIGINT, Disposition::Catch).unwrap();
962 system.set_disposition(SIGUSR1, Disposition::Catch).unwrap();
963
964 let mut context = Context::from_waker(Waker::noop());
965 let mut future = Box::pin(system.wait_for_signals());
966 let result = future.as_mut().poll(&mut context);
967 assert_eq!(result, Poll::Pending);
968
969 {
970 let mut state = state.borrow_mut();
971 let process = state.processes.get_mut(&process_id).unwrap();
972 assert!(process.blocked_signals().contains(&SIGCHLD));
973 assert!(process.blocked_signals().contains(&SIGINT));
974 assert!(process.blocked_signals().contains(&SIGUSR1));
975 let _ = process.raise_signal(SIGCHLD);
976 let _ = process.raise_signal(SIGINT);
977 }
978 let result = future.as_mut().poll(&mut context);
979 assert_eq!(result, Poll::Pending);
980
981 system.select(false).unwrap();
982 let result = future.as_mut().poll(&mut context);
983 assert_matches!(result, Poll::Ready(signals) => {
984 assert_eq!(signals.len(), 2);
985 assert!(signals.contains(&SIGCHLD));
986 assert!(signals.contains(&SIGINT));
987 });
988 }
989
990 #[test]
991 fn shared_system_wait_for_signal_returns_on_caught() {
992 let system = VirtualSystem::new();
993 let process_id = system.process_id;
994 let state = Rc::clone(&system.state);
995 let mut system = SharedSystem::new(Box::new(system));
996 system.set_disposition(SIGCHLD, Disposition::Catch).unwrap();
997
998 let mut context = Context::from_waker(Waker::noop());
999 let mut future = Box::pin(system.wait_for_signal(SIGCHLD));
1000 let result = future.as_mut().poll(&mut context);
1001 assert_eq!(result, Poll::Pending);
1002
1003 {
1004 let mut state = state.borrow_mut();
1005 let process = state.processes.get_mut(&process_id).unwrap();
1006 assert!(process.blocked_signals().contains(&SIGCHLD));
1007 let _ = process.raise_signal(SIGCHLD);
1008 }
1009 let result = future.as_mut().poll(&mut context);
1010 assert_eq!(result, Poll::Pending);
1011
1012 system.select(false).unwrap();
1013 let result = future.as_mut().poll(&mut context);
1014 assert_eq!(result, Poll::Ready(()));
1015 }
1016
1017 #[test]
1018 fn shared_system_wait_for_signal_ignores_irrelevant_signals() {
1019 let system = VirtualSystem::new();
1020 let process_id = system.process_id;
1021 let state = Rc::clone(&system.state);
1022 let mut system = SharedSystem::new(Box::new(system));
1023 system.set_disposition(SIGINT, Disposition::Catch).unwrap();
1024 system.set_disposition(SIGTERM, Disposition::Catch).unwrap();
1025
1026 let mut context = Context::from_waker(Waker::noop());
1027 let mut future = Box::pin(system.wait_for_signal(SIGINT));
1028 let result = future.as_mut().poll(&mut context);
1029 assert_eq!(result, Poll::Pending);
1030
1031 {
1032 let mut state = state.borrow_mut();
1033 let process = state.processes.get_mut(&process_id).unwrap();
1034 let _ = process.raise_signal(SIGCHLD);
1035 let _ = process.raise_signal(SIGTERM);
1036 }
1037 system.select(false).unwrap();
1038
1039 let result = future.as_mut().poll(&mut context);
1040 assert_eq!(result, Poll::Pending);
1041 }
1042
1043 #[test]
1044 fn shared_system_select_consumes_all_pending_signals() {
1045 let system = VirtualSystem::new();
1046 let process_id = system.process_id;
1047 let state = Rc::clone(&system.state);
1048 let mut system = SharedSystem::new(Box::new(system));
1049 system.set_disposition(SIGINT, Disposition::Catch).unwrap();
1050 system.set_disposition(SIGTERM, Disposition::Catch).unwrap();
1051
1052 {
1053 let mut state = state.borrow_mut();
1054 let process = state.processes.get_mut(&process_id).unwrap();
1055 let _ = process.raise_signal(SIGINT);
1056 let _ = process.raise_signal(SIGTERM);
1057 }
1058 system.select(false).unwrap();
1059
1060 let state = state.borrow();
1061 let process = state.processes.get(&process_id).unwrap();
1062 let blocked = process.blocked_signals();
1063 assert!(blocked.contains(&SIGINT));
1064 assert!(blocked.contains(&SIGTERM));
1065 let pending = process.pending_signals();
1066 assert!(!pending.contains(&SIGINT));
1067 assert!(!pending.contains(&SIGTERM));
1068 }
1069
1070 #[test]
1071 fn shared_system_select_does_not_wake_signal_waiters_on_io() {
1072 let system = VirtualSystem::new();
1073 let mut system_1 = SharedSystem::new(Box::new(system));
1074 let mut system_2 = system_1.clone();
1075 let mut system_3 = system_1.clone();
1076 let (reader, writer) = system_1.pipe().unwrap();
1077 system_2
1078 .set_disposition(SIGCHLD, Disposition::Catch)
1079 .unwrap();
1080
1081 let mut buffer = [0];
1082 let mut read_future = Box::pin(system_1.read_async(reader, &mut buffer));
1083 let mut signal_future = Box::pin(system_2.wait_for_signals());
1084 let mut context = Context::from_waker(Waker::noop());
1085 let result = read_future.as_mut().poll(&mut context);
1086 assert_eq!(result, Poll::Pending);
1087 let result = signal_future.as_mut().poll(&mut context);
1088 assert_eq!(result, Poll::Pending);
1089 system_3.write(writer, &[42]).unwrap();
1090 system_3.select(false).unwrap();
1091
1092 let result = read_future.as_mut().poll(&mut context);
1093 assert_eq!(result, Poll::Ready(Ok(1)));
1094 let result = signal_future.as_mut().poll(&mut context);
1095 assert_eq!(result, Poll::Pending);
1096 }
1097
1098 #[test]
1099 fn shared_system_select_poll() {
1100 let system = VirtualSystem::new();
1101 let state = Rc::clone(&system.state);
1102 let system = SharedSystem::new(Box::new(system));
1103 let start = Instant::now();
1104 state.borrow_mut().now = Some(start);
1105 let target = start + Duration::from_millis(1_125);
1106
1107 let mut future = Box::pin(system.wait_until(target));
1108 let mut context = Context::from_waker(Waker::noop());
1109 let poll = future.as_mut().poll(&mut context);
1110 assert_eq!(poll, Poll::Pending);
1111
1112 system.select(true).unwrap();
1113 let poll = future.as_mut().poll(&mut context);
1114 assert_eq!(poll, Poll::Pending);
1115 assert_eq!(state.borrow().now, Some(start));
1116 }
1117}