1use super::CaughtSignals;
20use super::Chdir;
21use super::ChildProcessStarter;
22use super::Clock;
23use super::CpuTimes;
24use super::Dir;
25use super::Disposition;
26use super::Dup;
27use super::Errno;
28use super::Exec;
29use super::Exit;
30use super::Fcntl;
31use super::FdFlag;
32use super::Fork;
33use super::Fstat;
34use super::GetCwd;
35use super::GetPid;
36use super::GetPw;
37use super::GetRlimit;
38use super::GetSigaction;
39use super::GetUid;
40use super::Gid;
41use super::IsExecutableFile;
42use super::Isatty;
43use super::LimitPair;
44use super::Mode;
45use super::OfdAccess;
46use super::Open;
47use super::OpenFlag;
48use super::Path;
49use super::PathBuf;
50use super::Pipe;
51use super::Read;
52use super::Resource;
53use super::Result;
54use super::Seek;
55use super::Select;
56use super::SelectSystem;
57use super::SendSignal;
58use super::SetPgid;
59use super::SetRlimit;
60use super::ShellPath;
61use super::Sigaction;
62use super::Sigmask;
63use super::SigmaskOp;
64use super::SignalStatus;
65use super::SignalSystem;
66use super::Signals;
67use super::Sysconf;
68use super::TcGetPgrp;
69use super::TcSetPgrp;
70use super::Times;
71use super::Uid;
72use super::Umask;
73use super::UnixString;
74use super::Wait;
75use super::Write;
76use super::signal;
77#[cfg(doc)]
78use crate::Env;
79use crate::io::Fd;
80use crate::job::Pid;
81use crate::job::ProcessState;
82use crate::semantics::ExitStatus;
83use crate::system::Close;
84use enumset::EnumSet;
85use std::cell::RefCell;
86use std::convert::Infallible;
87use std::ffi::CStr;
88use std::ffi::CString;
89use std::ffi::c_int;
90use std::future::poll_fn;
91use std::io::SeekFrom;
92use std::ops::RangeInclusive;
93use std::rc::Rc;
94use std::task::Poll;
95use std::time::Duration;
96use std::time::Instant;
97
98#[deprecated(since = "0.13.0", note = "use `Concurrent` instead")]
153#[derive(Debug)]
154pub struct SharedSystem<S>(pub(super) Rc<RefCell<SelectSystem<S>>>);
155
156#[allow(deprecated)]
157impl<S> SharedSystem<S> {
158 pub fn new(system: S) -> Self {
160 SharedSystem(Rc::new(RefCell::new(SelectSystem::new(system))))
161 }
162
163 pub async fn read_async(&self, fd: Fd, buffer: &mut [u8]) -> Result<usize>
168 where
169 S: Fcntl + Read,
170 {
171 let was_nonblocking = self.get_and_set_nonblocking(fd, true)?;
172
173 let waker = Rc::new(RefCell::new(None));
178
179 let result = loop {
180 match self.read(fd, buffer).await {
181 #[allow(unreachable_patterns)]
183 Err(Errno::EAGAIN | Errno::EWOULDBLOCK) => {
184 let mut first_time = true;
185 poll_fn(|context| {
186 if first_time {
187 first_time = false;
189 *waker.borrow_mut() = Some(context.waker().clone());
190 self.0.borrow_mut().add_reader(fd, Rc::downgrade(&waker));
191 Poll::Pending
192 } else {
193 Poll::Ready(())
195 }
196 })
197 .await;
198 }
199
200 Err(Errno::EINTR) => (),
201
202 result => break result,
203 }
204 };
205
206 self.get_and_set_nonblocking(fd, was_nonblocking).ok();
207
208 result
209 }
210
211 pub async fn write_all(&self, fd: Fd, mut buffer: &[u8]) -> Result<usize>
220 where
221 S: Fcntl + Write,
222 {
223 if buffer.is_empty() {
224 return Ok(0);
225 }
226
227 let was_nonblocking = self.get_and_set_nonblocking(fd, true)?;
228 let mut written = 0;
229
230 let waker = Rc::new(RefCell::new(None));
235
236 let result = loop {
237 match self.write(fd, buffer).await {
238 Ok(count) => {
239 written += count;
240 buffer = &buffer[count..];
241 if buffer.is_empty() {
242 break Ok(written);
243 }
244 }
245
246 Err(Errno::EINTR) => (),
247
248 #[allow(unreachable_patterns)]
250 Err(Errno::EAGAIN | Errno::EWOULDBLOCK) => {
251 let mut first_time = true;
252 poll_fn(|context| {
253 if first_time {
254 first_time = false;
256 *waker.borrow_mut() = Some(context.waker().clone());
257 self.0.borrow_mut().add_writer(fd, Rc::downgrade(&waker));
258 Poll::Pending
259 } else {
260 Poll::Ready(())
262 }
263 })
264 .await;
265 }
266
267 Err(error) => break Err(error),
268 }
269 };
270
271 self.get_and_set_nonblocking(fd, was_nonblocking).ok();
272
273 result
274 }
275
276 pub async fn print_error(&self, message: &str)
278 where
279 S: Fcntl + Write,
280 {
281 _ = self.write_all(Fd::STDERR, message.as_bytes()).await;
282 }
283
284 pub async fn wait_until(&self, target: Instant)
286 where
287 S: Clock,
288 {
289 let waker = Rc::new(RefCell::new(None));
294
295 poll_fn(|context| {
296 let mut system = self.0.borrow_mut();
297 let now = system.now();
298 if now >= target {
299 return Poll::Ready(());
300 }
301 *waker.borrow_mut() = Some(context.waker().clone());
302 system.add_timeout(target, Rc::downgrade(&waker));
303 Poll::Pending
304 })
305 .await
306 }
307
308 pub async fn wait_for_signals(&self) -> Rc<[signal::Number]> {
320 let status = self.0.borrow_mut().add_signal_waker();
321 poll_fn(|context| {
322 let mut status = status.borrow_mut();
323 let dummy_status = SignalStatus::Expected(None);
324 let old_status = std::mem::replace(&mut *status, dummy_status);
325 match old_status {
326 SignalStatus::Caught(signals) => Poll::Ready(signals),
327 SignalStatus::Expected(_) => {
328 *status = SignalStatus::Expected(Some(context.waker().clone()));
329 Poll::Pending
330 }
331 }
332 })
333 .await
334 }
335
336 pub async fn wait_for_signal(&self, signal: signal::Number) {
346 while !self.wait_for_signals().await.contains(&signal) {}
347 }
348
349 pub fn select(&self, poll: bool) -> Result<()>
366 where
367 S: Select + CaughtSignals + Clock,
368 {
369 use std::task::{Context, Poll, Waker};
370 let mut future = std::pin::pin!(SelectSystem::select(&self.0, poll));
371 let mut context = Context::from_waker(Waker::noop());
372 match future.as_mut().poll(&mut context) {
373 Poll::Ready(result) => result,
374 Poll::Pending => Ok(()),
375 }
376 }
377
378 pub async fn select_async(&self) -> Result<()>
392 where
393 S: Select + CaughtSignals + Clock,
394 {
395 SelectSystem::select(&self.0, false).await
396 }
397
398 pub fn new_child_process(&self) -> Result<ChildProcessStarter<S>>
402 where
403 S: Fork,
404 {
405 self.0.borrow().new_child_process()
406 }
407}
408
409#[allow(deprecated)]
410impl<S> Clone for SharedSystem<S> {
411 fn clone(&self) -> Self {
412 SharedSystem(self.0.clone())
413 }
414}
415
416#[allow(deprecated)]
418impl<T: Fstat> Fstat for SharedSystem<T> {
419 type Stat = T::Stat;
420
421 fn fstat(&self, fd: Fd) -> Result<Self::Stat> {
422 self.0.borrow().fstat(fd)
423 }
424 fn fstatat(&self, dir_fd: Fd, path: &CStr, follow_symlinks: bool) -> Result<Self::Stat> {
425 self.0.borrow().fstatat(dir_fd, path, follow_symlinks)
426 }
427}
428
429#[allow(deprecated)]
431impl<T: IsExecutableFile> IsExecutableFile for SharedSystem<T> {
432 fn is_executable_file(&self, path: &CStr) -> bool {
433 self.0.borrow().is_executable_file(path)
434 }
435}
436
437#[allow(deprecated)]
439impl<T: Pipe> Pipe for SharedSystem<T> {
440 fn pipe(&self) -> Result<(Fd, Fd)> {
441 self.0.borrow().pipe()
442 }
443}
444
445#[allow(deprecated)]
447impl<T: Dup> Dup for SharedSystem<T> {
448 fn dup(&self, from: Fd, to_min: Fd, flags: EnumSet<FdFlag>) -> Result<Fd> {
449 self.0.borrow().dup(from, to_min, flags)
450 }
451 fn dup2(&self, from: Fd, to: Fd) -> Result<Fd> {
452 self.0.borrow().dup2(from, to)
453 }
454}
455
456#[allow(deprecated)]
457impl<T: Open> Open for SharedSystem<T> {
458 fn open(
459 &self,
460 path: &CStr,
461 access: OfdAccess,
462 flags: EnumSet<OpenFlag>,
463 mode: Mode,
464 ) -> impl Future<Output = Result<Fd>> + use<T> {
465 self.0.borrow().open(path, access, flags, mode)
466 }
467 fn open_tmpfile(&self, parent_dir: &Path) -> Result<Fd> {
468 self.0.borrow().open_tmpfile(parent_dir)
469 }
470 fn fdopendir(&self, fd: Fd) -> Result<impl Dir + use<T>> {
471 self.0.borrow().fdopendir(fd)
472 }
473 fn opendir(&self, path: &CStr) -> Result<impl Dir + use<T>> {
474 self.0.borrow().opendir(path)
475 }
476}
477
478#[allow(deprecated)]
479impl<T: Close> Close for SharedSystem<T> {
480 fn close(&self, fd: Fd) -> Result<()> {
481 self.0.borrow().close(fd)
482 }
483}
484
485#[allow(deprecated)]
487impl<T: Fcntl> Fcntl for SharedSystem<T> {
488 fn ofd_access(&self, fd: Fd) -> Result<OfdAccess> {
489 self.0.borrow().ofd_access(fd)
490 }
491 fn get_and_set_nonblocking(&self, fd: Fd, nonblocking: bool) -> Result<bool> {
492 self.0.borrow().get_and_set_nonblocking(fd, nonblocking)
493 }
494 fn fcntl_getfd(&self, fd: Fd) -> Result<EnumSet<FdFlag>> {
495 self.0.borrow().fcntl_getfd(fd)
496 }
497 fn fcntl_setfd(&self, fd: Fd, flags: EnumSet<FdFlag>) -> Result<()> {
498 self.0.borrow().fcntl_setfd(fd, flags)
499 }
500}
501
502#[allow(deprecated)]
504impl<T: Read> Read for SharedSystem<T> {
505 fn read<'a>(
506 &self,
507 fd: Fd,
508 buffer: &'a mut [u8],
509 ) -> impl Future<Output = Result<usize>> + use<'a, T> {
510 self.0.borrow().read(fd, buffer)
511 }
512}
513
514#[allow(deprecated)]
516impl<T: Write> Write for SharedSystem<T> {
517 fn write<'a>(
518 &self,
519 fd: Fd,
520 buffer: &'a [u8],
521 ) -> impl Future<Output = Result<usize>> + use<'a, T> {
522 self.0.borrow().write(fd, buffer)
523 }
524}
525
526#[allow(deprecated)]
528impl<T: Seek> Seek for SharedSystem<T> {
529 fn lseek(&self, fd: Fd, position: SeekFrom) -> Result<u64> {
530 self.0.borrow().lseek(fd, position)
531 }
532}
533
534#[allow(deprecated)]
536impl<T: Umask> Umask for SharedSystem<T> {
537 fn umask(&self, new_mask: Mode) -> Mode {
538 self.0.borrow().umask(new_mask)
539 }
540}
541
542#[allow(deprecated)]
544impl<T: GetCwd> GetCwd for SharedSystem<T> {
545 fn getcwd(&self) -> Result<PathBuf> {
546 self.0.borrow().getcwd()
547 }
548}
549
550#[allow(deprecated)]
552impl<T: Chdir> Chdir for SharedSystem<T> {
553 fn chdir(&self, path: &CStr) -> Result<()> {
554 self.0.borrow().chdir(path)
555 }
556}
557
558#[allow(deprecated)]
560impl<T: Clock> Clock for SharedSystem<T> {
561 fn now(&self) -> Instant {
562 self.0.borrow().now()
563 }
564}
565
566#[allow(deprecated)]
568impl<T: Times> Times for SharedSystem<T> {
569 fn times(&self) -> Result<CpuTimes> {
570 self.0.borrow().times()
571 }
572}
573
574#[allow(deprecated)]
576impl<T: GetPid> GetPid for SharedSystem<T> {
577 fn getsid(&self, pid: Pid) -> Result<Pid> {
578 self.0.borrow().getsid(pid)
579 }
580
581 fn getpid(&self) -> Pid {
582 self.0.borrow().getpid()
583 }
584
585 fn getppid(&self) -> Pid {
586 self.0.borrow().getppid()
587 }
588
589 fn getpgrp(&self) -> Pid {
590 self.0.borrow().getpgrp()
591 }
592}
593
594#[allow(deprecated)]
596impl<T: SetPgid> SetPgid for SharedSystem<T> {
597 fn setpgid(&self, pid: Pid, pgid: Pid) -> Result<()> {
598 self.0.borrow().setpgid(pid, pgid)
599 }
600}
601
602#[allow(deprecated)]
604impl<T: Signals> Signals for SharedSystem<T> {
605 const SIGABRT: signal::Number = T::SIGABRT;
606 const SIGALRM: signal::Number = T::SIGALRM;
607 const SIGBUS: signal::Number = T::SIGBUS;
608 const SIGCHLD: signal::Number = T::SIGCHLD;
609 const SIGCLD: Option<signal::Number> = T::SIGCLD;
610 const SIGCONT: signal::Number = T::SIGCONT;
611 const SIGEMT: Option<signal::Number> = T::SIGEMT;
612 const SIGFPE: signal::Number = T::SIGFPE;
613 const SIGHUP: signal::Number = T::SIGHUP;
614 const SIGILL: signal::Number = T::SIGILL;
615 const SIGINFO: Option<signal::Number> = T::SIGINFO;
616 const SIGINT: signal::Number = T::SIGINT;
617 const SIGIO: Option<signal::Number> = T::SIGIO;
618 const SIGIOT: signal::Number = T::SIGIOT;
619 const SIGKILL: signal::Number = T::SIGKILL;
620 const SIGLOST: Option<signal::Number> = T::SIGLOST;
621 const SIGPIPE: signal::Number = T::SIGPIPE;
622 const SIGPOLL: Option<signal::Number> = T::SIGPOLL;
623 const SIGPROF: signal::Number = T::SIGPROF;
624 const SIGPWR: Option<signal::Number> = T::SIGPWR;
625 const SIGQUIT: signal::Number = T::SIGQUIT;
626 const SIGSEGV: signal::Number = T::SIGSEGV;
627 const SIGSTKFLT: Option<signal::Number> = T::SIGSTKFLT;
628 const SIGSTOP: signal::Number = T::SIGSTOP;
629 const SIGSYS: signal::Number = T::SIGSYS;
630 const SIGTERM: signal::Number = T::SIGTERM;
631 const SIGTHR: Option<signal::Number> = T::SIGTHR;
632 const SIGTRAP: signal::Number = T::SIGTRAP;
633 const SIGTSTP: signal::Number = T::SIGTSTP;
634 const SIGTTIN: signal::Number = T::SIGTTIN;
635 const SIGTTOU: signal::Number = T::SIGTTOU;
636 const SIGURG: signal::Number = T::SIGURG;
637 const SIGUSR1: signal::Number = T::SIGUSR1;
638 const SIGUSR2: signal::Number = T::SIGUSR2;
639 const SIGVTALRM: signal::Number = T::SIGVTALRM;
640 const SIGWINCH: signal::Number = T::SIGWINCH;
641 const SIGXCPU: signal::Number = T::SIGXCPU;
642 const SIGXFSZ: signal::Number = T::SIGXFSZ;
643
644 fn sigrt_range(&self) -> Option<RangeInclusive<signal::Number>> {
645 self.0.borrow().sigrt_range()
646 }
647
648 fn iter_sigrt(&self) -> impl DoubleEndedIterator<Item = signal::Number> + use<T> {
649 self.0.borrow().iter_sigrt()
650 }
651
652 fn validate_signal(&self, number: signal::RawNumber) -> Option<(signal::Name, signal::Number)> {
653 self.0.borrow().validate_signal(number)
654 }
655}
656
657#[allow(deprecated)]
659impl<T: Sigmask> Sigmask for SharedSystem<T> {
660 fn sigmask(
661 &self,
662 op: Option<(SigmaskOp, &[signal::Number])>,
663 old_mask: Option<&mut Vec<signal::Number>>,
664 ) -> impl Future<Output = Result<()>> + use<T> {
665 (**self.0.borrow()).sigmask(op, old_mask)
666 }
667}
668
669#[allow(deprecated)]
671impl<T: Sigaction> GetSigaction for SharedSystem<T> {
672 fn get_sigaction(&self, signal: signal::Number) -> Result<Disposition> {
673 self.0.borrow().get_sigaction(signal)
674 }
675}
676
677#[allow(deprecated)]
679impl<T: Sigaction> Sigaction for SharedSystem<T> {
680 fn sigaction(&self, signal: signal::Number, action: Disposition) -> Result<Disposition> {
681 self.0.borrow().sigaction(signal, action)
682 }
683}
684
685#[allow(deprecated)]
687impl<T: CaughtSignals> CaughtSignals for SharedSystem<T> {
688 fn caught_signals(&self) -> Vec<signal::Number> {
689 self.0.borrow().caught_signals()
690 }
691}
692
693#[allow(deprecated)]
695impl<T: SendSignal> SendSignal for SharedSystem<T> {
696 fn kill(
697 &self,
698 target: Pid,
699 signal: Option<signal::Number>,
700 ) -> impl Future<Output = Result<()>> + use<T> {
701 self.0.borrow().kill(target, signal)
702 }
703 fn raise(&self, signal: signal::Number) -> impl Future<Output = Result<()>> + use<T> {
704 self.0.borrow().raise(signal)
705 }
706}
707
708#[allow(deprecated)]
710impl<T: Select> Select for SharedSystem<T> {
711 fn select<'a>(
712 &self,
713 readers: &'a mut Vec<Fd>,
714 writers: &'a mut Vec<Fd>,
715 timeout: Option<Duration>,
716 signal_mask: Option<&[signal::Number]>,
717 ) -> impl Future<Output = Result<c_int>> + use<'a, T> {
718 (**self.0.borrow()).select(readers, writers, timeout, signal_mask)
719 }
720}
721
722#[allow(deprecated)]
724impl<T: Isatty> Isatty for SharedSystem<T> {
725 fn isatty(&self, fd: Fd) -> bool {
726 self.0.borrow().isatty(fd)
727 }
728}
729
730#[allow(deprecated)]
732impl<T: TcGetPgrp> TcGetPgrp for SharedSystem<T> {
733 fn tcgetpgrp(&self, fd: Fd) -> Result<Pid> {
734 self.0.borrow().tcgetpgrp(fd)
735 }
736}
737
738#[allow(deprecated)]
740impl<T: TcSetPgrp> TcSetPgrp for SharedSystem<T> {
741 fn tcsetpgrp(&self, fd: Fd, pgid: Pid) -> impl Future<Output = Result<()>> + use<T> {
742 self.0.borrow().tcsetpgrp(fd, pgid)
743 }
744}
745
746#[allow(deprecated)]
748impl<T: Wait> Wait for SharedSystem<T> {
749 fn wait(&self, target: Pid) -> Result<Option<(Pid, ProcessState)>> {
750 self.0.borrow().wait(target)
751 }
752}
753
754#[allow(deprecated)]
756impl<T: Exec> Exec for SharedSystem<T> {
757 fn execve(
758 &self,
759 path: &CStr,
760 args: &[CString],
761 envs: &[CString],
762 ) -> impl Future<Output = Result<Infallible>> + use<T> {
763 self.0.borrow().execve(path, args, envs)
764 }
765}
766
767#[allow(deprecated)]
769impl<T: Exit> Exit for SharedSystem<T> {
770 fn exit(&self, exit_status: ExitStatus) -> impl Future<Output = Infallible> + use<T> {
771 self.0.borrow().exit(exit_status)
772 }
773}
774
775#[allow(deprecated)]
777impl<T: GetUid> GetUid for SharedSystem<T> {
778 fn getuid(&self) -> Uid {
779 self.0.borrow().getuid()
780 }
781 fn geteuid(&self) -> Uid {
782 self.0.borrow().geteuid()
783 }
784 fn getgid(&self) -> Gid {
785 self.0.borrow().getgid()
786 }
787 fn getegid(&self) -> Gid {
788 self.0.borrow().getegid()
789 }
790}
791
792#[allow(deprecated)]
794impl<T: GetPw> GetPw for SharedSystem<T> {
795 fn getpwnam_dir(&self, name: &CStr) -> Result<Option<PathBuf>> {
796 self.0.borrow().getpwnam_dir(name)
797 }
798}
799
800#[allow(deprecated)]
802impl<T: Sysconf> Sysconf for SharedSystem<T> {
803 fn confstr_path(&self) -> Result<UnixString> {
804 self.0.borrow().confstr_path()
805 }
806}
807
808#[allow(deprecated)]
810impl<T: ShellPath> ShellPath for SharedSystem<T> {
811 fn shell_path(&self) -> CString {
812 self.0.borrow().shell_path()
813 }
814}
815
816#[allow(deprecated)]
818impl<T: GetRlimit> GetRlimit for SharedSystem<T> {
819 fn getrlimit(&self, resource: Resource) -> Result<LimitPair> {
820 self.0.borrow().getrlimit(resource)
821 }
822}
823
824#[allow(deprecated)]
826impl<T: SetRlimit> SetRlimit for SharedSystem<T> {
827 fn setrlimit(&self, resource: Resource, limits: LimitPair) -> Result<()> {
828 self.0.borrow().setrlimit(resource, limits)
829 }
830}
831
832#[allow(deprecated)]
833impl<S: Signals + Sigmask + Sigaction> SignalSystem for SharedSystem<S> {
834 #[inline]
835 fn get_disposition(&self, signal: signal::Number) -> Result<Disposition> {
836 self.0.borrow().get_disposition(signal)
837 }
838
839 #[inline]
840 fn set_disposition(
841 &self,
842 signal: signal::Number,
843 disposition: Disposition,
844 ) -> impl Future<Output = Result<Disposition>> + use<S> {
845 let this = Rc::clone(&self.0);
846 async move { SelectSystem::set_disposition(&this, signal, disposition).await }
847 }
848}
849
850#[cfg(test)]
851#[allow(deprecated)]
852mod tests {
853 use super::super::r#virtual::PIPE_SIZE;
854 use super::super::r#virtual::VirtualSystem;
855 use super::super::r#virtual::{SIGCHLD, SIGINT, SIGTERM, SIGUSR1};
856 use super::*;
857 use crate::test_helper::WakeFlag;
858 use assert_matches::assert_matches;
859 use futures_util::FutureExt as _;
860 use std::sync::Arc;
861 use std::task::Context;
862 use std::task::Poll;
863 use std::task::Waker;
864 use std::time::Duration;
865
866 #[test]
867 fn shared_system_read_async_ready() {
868 let system = SharedSystem::new(VirtualSystem::new());
869 let (reader, writer) = system.pipe().unwrap();
870 system.write(writer, &[42]).now_or_never().unwrap().unwrap();
871
872 let mut buffer = [0; 2];
873 let result = system.read_async(reader, &mut buffer).now_or_never();
874 assert_eq!(result, Some(Ok(1)));
875 assert_eq!(buffer[..1], [42]);
876 }
877
878 #[test]
879 fn shared_system_read_async_not_ready_at_first() {
880 let system = VirtualSystem::new();
881 let process_id = system.process_id;
882 let state = Rc::clone(&system.state);
883 let system = SharedSystem::new(system);
884 let system2 = system.clone();
885 let (reader, writer) = system.pipe().unwrap();
886
887 let mut context = Context::from_waker(Waker::noop());
888 let mut buffer = [0; 2];
889 let mut future = Box::pin(system.read_async(reader, &mut buffer));
890 let result = future.as_mut().poll(&mut context);
891 assert_eq!(result, Poll::Pending);
892
893 let result = system2.select(false);
894 assert_eq!(result, Ok(()));
895 let result = future.as_mut().poll(&mut context);
896 assert_eq!(result, Poll::Pending);
897
898 state.borrow_mut().processes[&process_id].fds[&writer]
899 .open_file_description
900 .borrow_mut()
901 .write(&[56])
902 .unwrap();
903
904 let result = future.as_mut().poll(&mut context);
905 drop(future);
906 assert_eq!(result, Poll::Ready(Ok(1)));
907 assert_eq!(buffer[..1], [56]);
908 }
909
910 #[test]
911 fn shared_system_write_all_ready() {
912 let system = SharedSystem::new(VirtualSystem::new());
913 let (reader, writer) = system.pipe().unwrap();
914 let result = system.write_all(writer, &[17]).now_or_never().unwrap();
915 assert_eq!(result, Ok(1));
916
917 let mut buffer = [0; 2];
918 system
919 .read(reader, &mut buffer)
920 .now_or_never()
921 .unwrap()
922 .unwrap();
923 assert_eq!(buffer[..1], [17]);
924 }
925
926 #[test]
927 fn shared_system_write_all_not_ready_at_first() {
928 let system = VirtualSystem::new();
929 let process_id = system.process_id;
930 let state = Rc::clone(&system.state);
931 let system = SharedSystem::new(system);
932 let (reader, writer) = system.pipe().unwrap();
933
934 state.borrow_mut().processes[&process_id].fds[&writer]
935 .open_file_description
936 .borrow_mut()
937 .write(&[42; PIPE_SIZE])
938 .unwrap();
939
940 let mut context = Context::from_waker(Waker::noop());
941 let mut out_buffer = [87; PIPE_SIZE];
942 out_buffer[0] = 0;
943 out_buffer[1] = 1;
944 out_buffer[PIPE_SIZE - 2] = 0xFE;
945 out_buffer[PIPE_SIZE - 1] = 0xFF;
946 let mut future = Box::pin(system.write_all(writer, &out_buffer));
947 let result = future.as_mut().poll(&mut context);
948 assert_eq!(result, Poll::Pending);
949
950 let mut in_buffer = [0; PIPE_SIZE - 1];
951 state.borrow_mut().processes[&process_id].fds[&reader]
952 .open_file_description
953 .borrow_mut()
954 .read(&mut in_buffer)
955 .unwrap();
956 assert_eq!(in_buffer, [42; PIPE_SIZE - 1]);
957
958 let result = future.as_mut().poll(&mut context);
959 assert_eq!(result, Poll::Pending);
960
961 in_buffer[0] = 0;
962 state.borrow_mut().processes[&process_id].fds[&reader]
963 .open_file_description
964 .borrow_mut()
965 .read(&mut in_buffer[..1])
966 .unwrap();
967 assert_eq!(in_buffer[..1], [42; 1]);
968
969 let result = future.as_mut().poll(&mut context);
970 assert_eq!(result, Poll::Ready(Ok(out_buffer.len())));
971
972 state.borrow_mut().processes[&process_id].fds[&reader]
973 .open_file_description
974 .borrow_mut()
975 .read(&mut in_buffer)
976 .unwrap();
977 assert_eq!(in_buffer, out_buffer[..PIPE_SIZE - 1]);
978 state.borrow_mut().processes[&process_id].fds[&reader]
979 .open_file_description
980 .borrow_mut()
981 .read(&mut in_buffer)
982 .unwrap();
983 assert_eq!(in_buffer[..1], out_buffer[PIPE_SIZE - 1..]);
984 }
985
986 #[test]
987 fn shared_system_write_all_empty() {
988 let system = VirtualSystem::new();
989 let process_id = system.process_id;
990 let state = Rc::clone(&system.state);
991 let system = SharedSystem::new(system);
992 let (_reader, writer) = system.pipe().unwrap();
993
994 state.borrow_mut().processes[&process_id].fds[&writer]
995 .open_file_description
996 .borrow_mut()
997 .write(&[0; PIPE_SIZE])
998 .unwrap();
999
1000 let mut context = Context::from_waker(Waker::noop());
1002 let mut future = Box::pin(system.write_all(writer, &[]));
1003 let result = future.as_mut().poll(&mut context);
1004 assert_eq!(result, Poll::Ready(Ok(0)));
1005 }
1007
1008 #[test]
1011 fn shared_system_wait_until() {
1012 let system = VirtualSystem::new();
1013 let state = Rc::clone(&system.state);
1014 let system = SharedSystem::new(system);
1015 let start = Instant::now();
1016 state.borrow_mut().now = Some(start);
1017 let target = start + Duration::from_millis(1_125);
1018
1019 let mut future = Box::pin(system.wait_until(target));
1020
1021 let wake_flag = Arc::new(WakeFlag::new());
1022 let waker = Waker::from(wake_flag.clone());
1023 let mut context = Context::from_waker(&waker);
1024 let poll = future.as_mut().poll(&mut context);
1025 assert_eq!(poll, Poll::Pending);
1026 assert!(!wake_flag.is_woken());
1027
1028 state.borrow_mut().advance_time(target);
1029 system.select(false).unwrap();
1030 assert!(wake_flag.is_woken());
1031
1032 let wake_flag = Arc::new(WakeFlag::new());
1033 let waker = Waker::from(wake_flag.clone());
1034 let mut context = Context::from_waker(&waker);
1035 let poll = future.as_mut().poll(&mut context);
1036 assert_eq!(poll, Poll::Ready(()));
1037 }
1038
1039 #[test]
1040 fn shared_system_wait_for_signals() {
1041 let system = VirtualSystem::new();
1042 let process_id = system.process_id;
1043 let state = Rc::clone(&system.state);
1044 let system = SharedSystem::new(system);
1045 system
1046 .set_disposition(SIGCHLD, Disposition::Catch)
1047 .now_or_never()
1048 .unwrap()
1049 .unwrap();
1050 system
1051 .set_disposition(SIGINT, Disposition::Catch)
1052 .now_or_never()
1053 .unwrap()
1054 .unwrap();
1055 system
1056 .set_disposition(SIGUSR1, Disposition::Catch)
1057 .now_or_never()
1058 .unwrap()
1059 .unwrap();
1060
1061 let mut context = Context::from_waker(Waker::noop());
1062 let mut future = Box::pin(system.wait_for_signals());
1063 let result = future.as_mut().poll(&mut context);
1064 assert_eq!(result, Poll::Pending);
1065
1066 {
1067 let mut state = state.borrow_mut();
1068 let process = state.processes.get_mut(&process_id).unwrap();
1069 assert!(process.blocked_signals().contains(&SIGCHLD));
1070 assert!(process.blocked_signals().contains(&SIGINT));
1071 assert!(process.blocked_signals().contains(&SIGUSR1));
1072 let _ = process.raise_signal(SIGCHLD);
1073 let _ = process.raise_signal(SIGINT);
1074 }
1075 let result = future.as_mut().poll(&mut context);
1076 assert_eq!(result, Poll::Pending);
1077
1078 system.select(false).unwrap();
1079 let result = future.as_mut().poll(&mut context);
1080 assert_matches!(result, Poll::Ready(signals) => {
1081 assert_eq!(signals.len(), 2);
1082 assert!(signals.contains(&SIGCHLD));
1083 assert!(signals.contains(&SIGINT));
1084 });
1085 }
1086
1087 #[test]
1088 fn shared_system_wait_for_signal_returns_on_caught() {
1089 let system = VirtualSystem::new();
1090 let process_id = system.process_id;
1091 let state = Rc::clone(&system.state);
1092 let system = SharedSystem::new(system);
1093 system
1094 .set_disposition(SIGCHLD, Disposition::Catch)
1095 .now_or_never()
1096 .unwrap()
1097 .unwrap();
1098
1099 let mut context = Context::from_waker(Waker::noop());
1100 let mut future = Box::pin(system.wait_for_signal(SIGCHLD));
1101 let result = future.as_mut().poll(&mut context);
1102 assert_eq!(result, Poll::Pending);
1103
1104 {
1105 let mut state = state.borrow_mut();
1106 let process = state.processes.get_mut(&process_id).unwrap();
1107 assert!(process.blocked_signals().contains(&SIGCHLD));
1108 let _ = process.raise_signal(SIGCHLD);
1109 }
1110 let result = future.as_mut().poll(&mut context);
1111 assert_eq!(result, Poll::Pending);
1112
1113 system.select(false).unwrap();
1114 let result = future.as_mut().poll(&mut context);
1115 assert_eq!(result, Poll::Ready(()));
1116 }
1117
1118 #[test]
1119 fn shared_system_wait_for_signal_ignores_irrelevant_signals() {
1120 let system = VirtualSystem::new();
1121 let process_id = system.process_id;
1122 let state = Rc::clone(&system.state);
1123 let system = SharedSystem::new(system);
1124 system
1125 .set_disposition(SIGINT, Disposition::Catch)
1126 .now_or_never()
1127 .unwrap()
1128 .unwrap();
1129 system
1130 .set_disposition(SIGTERM, Disposition::Catch)
1131 .now_or_never()
1132 .unwrap()
1133 .unwrap();
1134
1135 let mut context = Context::from_waker(Waker::noop());
1136 let mut future = Box::pin(system.wait_for_signal(SIGINT));
1137 let result = future.as_mut().poll(&mut context);
1138 assert_eq!(result, Poll::Pending);
1139
1140 {
1141 let mut state = state.borrow_mut();
1142 let process = state.processes.get_mut(&process_id).unwrap();
1143 let _ = process.raise_signal(SIGCHLD);
1144 let _ = process.raise_signal(SIGTERM);
1145 }
1146 system.select(false).unwrap();
1147
1148 let result = future.as_mut().poll(&mut context);
1149 assert_eq!(result, Poll::Pending);
1150 }
1151
1152 #[test]
1153 fn shared_system_select_consumes_all_pending_signals() {
1154 let system = VirtualSystem::new();
1155 let process_id = system.process_id;
1156 let state = Rc::clone(&system.state);
1157 let system = SharedSystem::new(system);
1158 system
1159 .set_disposition(SIGINT, Disposition::Catch)
1160 .now_or_never()
1161 .unwrap()
1162 .unwrap();
1163 system
1164 .set_disposition(SIGTERM, Disposition::Catch)
1165 .now_or_never()
1166 .unwrap()
1167 .unwrap();
1168
1169 {
1170 let mut state = state.borrow_mut();
1171 let process = state.processes.get_mut(&process_id).unwrap();
1172 let _ = process.raise_signal(SIGINT);
1173 let _ = process.raise_signal(SIGTERM);
1174 }
1175 system.select(false).unwrap();
1176
1177 let state = state.borrow();
1178 let process = state.processes.get(&process_id).unwrap();
1179 let blocked = process.blocked_signals();
1180 assert!(blocked.contains(&SIGINT));
1181 assert!(blocked.contains(&SIGTERM));
1182 let pending = process.pending_signals();
1183 assert!(!pending.contains(&SIGINT));
1184 assert!(!pending.contains(&SIGTERM));
1185 }
1186
1187 #[test]
1188 fn shared_system_select_does_not_wake_signal_waiters_on_io() {
1189 let system = VirtualSystem::new();
1190 let system_1 = SharedSystem::new(system);
1191 let system_2 = system_1.clone();
1192 let system_3 = system_1.clone();
1193 let (reader, writer) = system_1.pipe().unwrap();
1194 system_2
1195 .set_disposition(SIGCHLD, Disposition::Catch)
1196 .now_or_never()
1197 .unwrap()
1198 .unwrap();
1199
1200 let mut buffer = [0];
1201 let mut read_future = Box::pin(system_1.read_async(reader, &mut buffer));
1202 let mut signal_future = Box::pin(system_2.wait_for_signals());
1203 let mut context = Context::from_waker(Waker::noop());
1204 let result = read_future.as_mut().poll(&mut context);
1205 assert_eq!(result, Poll::Pending);
1206 let result = signal_future.as_mut().poll(&mut context);
1207 assert_eq!(result, Poll::Pending);
1208 system_3
1209 .write(writer, &[42])
1210 .now_or_never()
1211 .unwrap()
1212 .unwrap();
1213 system_3.select(false).unwrap();
1214
1215 let result = read_future.as_mut().poll(&mut context);
1216 assert_eq!(result, Poll::Ready(Ok(1)));
1217 let result = signal_future.as_mut().poll(&mut context);
1218 assert_eq!(result, Poll::Pending);
1219 }
1220
1221 #[test]
1222 fn shared_system_select_poll() {
1223 let system = VirtualSystem::new();
1224 let state = Rc::clone(&system.state);
1225 let system = SharedSystem::new(system);
1226 let start = Instant::now();
1227 state.borrow_mut().now = Some(start);
1228 let target = start + Duration::from_millis(1_125);
1229
1230 let mut future = Box::pin(system.wait_until(target));
1231 let mut context = Context::from_waker(Waker::noop());
1232 let poll = future.as_mut().poll(&mut context);
1233 assert_eq!(poll, Poll::Pending);
1234
1235 system.select(true).unwrap();
1236 let poll = future.as_mut().poll(&mut context);
1237 assert_eq!(poll, Poll::Pending);
1238 assert_eq!(state.borrow().now, Some(start));
1239 }
1240}