pub struct SharedSystem(/* private fields */);Expand description
System shared by a reference counter.
A SharedSystem is a reference-counted container of a System instance
accompanied with an internal state for supporting asynchronous interactions
with the system. As it is reference-counted, cloning a SharedSystem
instance only increments the reference count without cloning the backing
system instance. This behavior allows calling SharedSystem’s methods
concurrently from different async tasks that each have a SharedSystem
instance sharing the same state.
SharedSystem implements System by delegating to the contained system
instance. You should avoid calling some of the System methods, however.
Prefer async functions provided by SharedSystem (e.g.,
read_async) over raw system functions (e.g.,
read).
The following example illustrates how multiple concurrent tasks are run in a single-threaded pool:
let mut system = SharedSystem::new(Box::new(VirtualSystem::new()));
let mut system2 = system.clone();
let mut system3 = system.clone();
let (reader, writer) = system.pipe().unwrap();
let mut executor = futures_executor::LocalPool::new();
// We add a task that tries to read from the pipe, but nothing has been
// written to it, so the task is stalled.
let read_task = executor.spawner().spawn_local_with_handle(async move {
let mut buffer = [0; 1];
system.read_async(reader, &mut buffer).await.unwrap();
buffer[0]
});
executor.run_until_stalled();
// Let's add a task that writes to the pipe.
executor.spawner().spawn_local(async move {
system2.write_all(writer, &[123]).await.unwrap();
});
executor.run_until_stalled();
// The write task has written a byte to the pipe, but the read task is still
// stalled. We need to wake it up by calling `select`.
system3.select(false).unwrap();
// Now the read task can proceed to the end.
let number = executor.run_until(read_task.unwrap());
assert_eq!(number, 123);If there is a child process in the VirtualSystem, you should call
SystemState::select_all in
addition to SharedSystem::select so that the child process task is woken
up when needed.
(TBD code example)
Implementations§
Sourcepub async fn read_async(&self, fd: Fd, buffer: &mut [u8]) -> Result<usize>
pub async fn read_async(&self, fd: Fd, buffer: &mut [u8]) -> Result<usize>
Reads from the file descriptor.
This function waits for one or more bytes to be available for reading. If successful, returns the number of bytes read.
Sourcepub async fn write_all(&self, fd: Fd, buffer: &[u8]) -> Result<usize>
pub async fn write_all(&self, fd: Fd, buffer: &[u8]) -> Result<usize>
Writes to the file descriptor.
This function calls System::write repeatedly until the whole
buffer is written to the FD. If the buffer is empty, write is not
called at all, so any error that would be returned from write is not
returned.
This function silently ignores signals that may interrupt writes.
Sourcepub async fn print_error(&self, message: &str)
pub async fn print_error(&self, message: &str)
Convenience function for printing a message to the standard error
Sourcepub async fn wait_until(&self, target: Instant)
pub async fn wait_until(&self, target: Instant)
Waits until the specified time point.
Sourcepub async fn wait_for_signals(&self) -> Rc<[Number]>
pub async fn wait_for_signals(&self) -> Rc<[Number]>
Waits for some signals to be delivered to this process.
Before calling this function, you need to set the signal
disposition to Catch. Without doing so, this
function cannot detect the receipt of the signals.
Returns an array of signals that were caught.
If this SharedSystem is part of an Env, you should call
Env::wait_for_signals rather than calling this function directly
so that the trap set can remember the caught signal.
Sourcepub async fn wait_for_signal(&self, signal: Number)
pub async fn wait_for_signal(&self, signal: Number)
Waits for a signal to be delivered to this process.
Before calling this function, you need to set the signal
disposition to Catch.
Without doing so, this function cannot detect the receipt of the signal.
If this SharedSystem is part of an Env, you should call
Env::wait_for_signal rather than calling this function directly
so that the trap set can remember the caught signal.
Sourcepub fn select(&self, poll: bool) -> Result<()>
pub fn select(&self, poll: bool) -> Result<()>
Waits for a next event to occur.
This function calls System::select with arguments computed from the
current internal state of the SharedSystem. It will wake up tasks
waiting for the file descriptor to be ready in
read_async and write_all or
for a signal to be caught in wait_for_signal.
If no tasks are woken for FDs or signals and poll is false, this
function will block until the first task waiting for a specific time
point is woken.
If poll is true, this function does not block, so it may not wake up any tasks.
This function may wake up a task even if the condition it is expecting has not yet been met.
Trait Implementations§
Source§fn clone(&self) -> SharedSystem
fn clone(&self) -> SharedSystem
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§fn signal_name_from_number(&self, number: Number) -> Name
fn signal_name_from_number(&self, number: Number) -> Name
Source§fn signal_number_from_name(&self, name: Name) -> Option<Number>
fn signal_number_from_name(&self, name: Name) -> Option<Number>
Source§fn get_disposition(&self, signal: Number) -> Result<Disposition>
fn get_disposition(&self, signal: Number) -> Result<Disposition>
Source§fn set_disposition(
&mut self,
signal: Number,
disposition: Disposition,
) -> Result<Disposition>
fn set_disposition( &mut self, signal: Number, disposition: Disposition, ) -> Result<Disposition>
Source§fn signal_name_from_number(&self, number: Number) -> Name
fn signal_name_from_number(&self, number: Number) -> Name
Source§fn signal_number_from_name(&self, name: Name) -> Option<Number>
fn signal_number_from_name(&self, name: Name) -> Option<Number>
Source§fn get_disposition(&self, signal: Number) -> Result<Disposition>
fn get_disposition(&self, signal: Number) -> Result<Disposition>
Source§fn set_disposition(
&mut self,
signal: Number,
disposition: Disposition,
) -> Result<Disposition>
fn set_disposition( &mut self, signal: Number, disposition: Disposition, ) -> Result<Disposition>
This implementation only requires a non-mutable reference to the shared
system because it uses RefCell to access the contained system instance.
Source§fn fstatat(
&self,
dir_fd: Fd,
path: &CStr,
follow_symlinks: bool,
) -> Result<Stat>
fn fstatat( &self, dir_fd: Fd, path: &CStr, follow_symlinks: bool, ) -> Result<Stat>
Source§fn is_executable_file(&self, path: &CStr) -> bool
fn is_executable_file(&self, path: &CStr) -> bool
Source§fn is_directory(&self, path: &CStr) -> bool
fn is_directory(&self, path: &CStr) -> bool
Source§fn dup(&mut self, from: Fd, to_min: Fd, flags: EnumSet<FdFlag>) -> Result<Fd>
fn dup(&mut self, from: Fd, to_min: Fd, flags: EnumSet<FdFlag>) -> Result<Fd>
Source§fn open(
&mut self,
path: &CStr,
access: OfdAccess,
flags: EnumSet<OpenFlag>,
mode: Mode,
) -> Result<Fd>
fn open( &mut self, path: &CStr, access: OfdAccess, flags: EnumSet<OpenFlag>, mode: Mode, ) -> Result<Fd>
Source§fn open_tmpfile(&mut self, parent_dir: &Path) -> Result<Fd>
fn open_tmpfile(&mut self, parent_dir: &Path) -> Result<Fd>
Source§fn ofd_access(&self, fd: Fd) -> Result<OfdAccess>
fn ofd_access(&self, fd: Fd) -> Result<OfdAccess>
Source§fn get_and_set_nonblocking(&mut self, fd: Fd, nonblocking: bool) -> Result<bool>
fn get_and_set_nonblocking(&mut self, fd: Fd, nonblocking: bool) -> Result<bool>
Source§fn fcntl_getfd(&self, fd: Fd) -> Result<EnumSet<FdFlag>>
fn fcntl_getfd(&self, fd: Fd) -> Result<EnumSet<FdFlag>>
Source§fn fcntl_setfd(&mut self, fd: Fd, flags: EnumSet<FdFlag>) -> Result<()>
fn fcntl_setfd(&mut self, fd: Fd, flags: EnumSet<FdFlag>) -> Result<()>
Source§fn isatty(&self, fd: Fd) -> bool
fn isatty(&self, fd: Fd) -> bool
Source§fn read(&mut self, fd: Fd, buffer: &mut [u8]) -> Result<usize>
fn read(&mut self, fd: Fd, buffer: &mut [u8]) -> Result<usize>
Source§fn write(&mut self, fd: Fd, buffer: &[u8]) -> Result<usize>
fn write(&mut self, fd: Fd, buffer: &[u8]) -> Result<usize>
Source§fn lseek(&mut self, fd: Fd, position: SeekFrom) -> Result<u64>
fn lseek(&mut self, fd: Fd, position: SeekFrom) -> Result<u64>
Source§fn fdopendir(&mut self, fd: Fd) -> Result<Box<dyn Dir>>
fn fdopendir(&mut self, fd: Fd) -> Result<Box<dyn Dir>>
Source§fn opendir(&mut self, path: &CStr) -> Result<Box<dyn Dir>>
fn opendir(&mut self, path: &CStr) -> Result<Box<dyn Dir>>
Source§fn validate_signal(&self, number: RawNumber) -> Option<(Name, Number)>
fn validate_signal(&self, number: RawNumber) -> Option<(Name, Number)>
Source§fn signal_number_from_name(&self, name: Name) -> Option<Number>
fn signal_number_from_name(&self, name: Name) -> Option<Number>
Source§fn sigmask(
&mut self,
op: Option<(SigmaskOp, &[Number])>,
old_mask: Option<&mut Vec<Number>>,
) -> Result<()>
fn sigmask( &mut self, op: Option<(SigmaskOp, &[Number])>, old_mask: Option<&mut Vec<Number>>, ) -> Result<()>
Source§fn get_sigaction(&self, signal: Number) -> Result<Disposition>
fn get_sigaction(&self, signal: Number) -> Result<Disposition>
Source§fn sigaction(
&mut self,
signal: Number,
action: Disposition,
) -> Result<Disposition>
fn sigaction( &mut self, signal: Number, action: Disposition, ) -> Result<Disposition>
Source§fn caught_signals(&mut self) -> Vec<Number>
fn caught_signals(&mut self) -> Vec<Number>
Source§fn kill(
&mut self,
target: Pid,
signal: Option<Number>,
) -> FlexFuture<Result<()>> ⓘ
fn kill( &mut self, target: Pid, signal: Option<Number>, ) -> FlexFuture<Result<()>> ⓘ
Source§fn raise(&mut self, signal: Number) -> FlexFuture<Result<()>> ⓘ
fn raise(&mut self, signal: Number) -> FlexFuture<Result<()>> ⓘ
Source§fn select(
&mut self,
readers: &mut Vec<Fd>,
writers: &mut Vec<Fd>,
timeout: Option<Duration>,
signal_mask: Option<&[Number]>,
) -> Result<c_int>
fn select( &mut self, readers: &mut Vec<Fd>, writers: &mut Vec<Fd>, timeout: Option<Duration>, signal_mask: Option<&[Number]>, ) -> Result<c_int>
Source§fn getsid(&self, pid: Pid) -> Result<Pid>
fn getsid(&self, pid: Pid) -> Result<Pid>
Source§fn setpgid(&mut self, pid: Pid, pgid: Pid) -> Result<()>
fn setpgid(&mut self, pid: Pid, pgid: Pid) -> Result<()>
Source§fn tcgetpgrp(&self, fd: Fd) -> Result<Pid>
fn tcgetpgrp(&self, fd: Fd) -> Result<Pid>
Source§fn tcsetpgrp(&mut self, fd: Fd, pgid: Pid) -> Result<()>
fn tcsetpgrp(&mut self, fd: Fd, pgid: Pid) -> Result<()>
Source§fn new_child_process(&mut self) -> Result<ChildProcessStarter>
fn new_child_process(&mut self) -> Result<ChildProcessStarter>
Source§fn wait(&mut self, target: Pid) -> Result<Option<(Pid, ProcessState)>>
fn wait(&mut self, target: Pid) -> Result<Option<(Pid, ProcessState)>>
Source§fn execve(
&mut self,
path: &CStr,
args: &[CString],
envs: &[CString],
) -> FlexFuture<Result<Infallible>> ⓘ
fn execve( &mut self, path: &CStr, args: &[CString], envs: &[CString], ) -> FlexFuture<Result<Infallible>> ⓘ
Source§fn exit(&mut self, exit_status: ExitStatus) -> FlexFuture<Infallible> ⓘ
fn exit(&mut self, exit_status: ExitStatus) -> FlexFuture<Infallible> ⓘ
Source§fn getpwnam_dir(&self, name: &CStr) -> Result<Option<PathBuf>>
fn getpwnam_dir(&self, name: &CStr) -> Result<Option<PathBuf>>
Source§fn confstr_path(&self) -> Result<UnixString>
fn confstr_path(&self) -> Result<UnixString>
$PATH value where all standard utilities are
expected to be found. Read moreSource§fn shell_path(&self) -> CString
fn shell_path(&self) -> CString
Source§fn fstatat(
&self,
dir_fd: Fd,
path: &CStr,
follow_symlinks: bool,
) -> Result<Stat>
fn fstatat( &self, dir_fd: Fd, path: &CStr, follow_symlinks: bool, ) -> Result<Stat>
Source§fn is_executable_file(&self, path: &CStr) -> bool
fn is_executable_file(&self, path: &CStr) -> bool
Source§fn is_directory(&self, path: &CStr) -> bool
fn is_directory(&self, path: &CStr) -> bool
Source§fn dup(&mut self, from: Fd, to_min: Fd, flags: EnumSet<FdFlag>) -> Result<Fd>
fn dup(&mut self, from: Fd, to_min: Fd, flags: EnumSet<FdFlag>) -> Result<Fd>
Source§fn open(
&mut self,
path: &CStr,
access: OfdAccess,
flags: EnumSet<OpenFlag>,
mode: Mode,
) -> Result<Fd>
fn open( &mut self, path: &CStr, access: OfdAccess, flags: EnumSet<OpenFlag>, mode: Mode, ) -> Result<Fd>
Source§fn open_tmpfile(&mut self, parent_dir: &Path) -> Result<Fd>
fn open_tmpfile(&mut self, parent_dir: &Path) -> Result<Fd>
Source§fn ofd_access(&self, fd: Fd) -> Result<OfdAccess>
fn ofd_access(&self, fd: Fd) -> Result<OfdAccess>
Source§fn get_and_set_nonblocking(&mut self, fd: Fd, nonblocking: bool) -> Result<bool>
fn get_and_set_nonblocking(&mut self, fd: Fd, nonblocking: bool) -> Result<bool>
Source§fn fcntl_getfd(&self, fd: Fd) -> Result<EnumSet<FdFlag>>
fn fcntl_getfd(&self, fd: Fd) -> Result<EnumSet<FdFlag>>
Source§fn fcntl_setfd(&mut self, fd: Fd, flags: EnumSet<FdFlag>) -> Result<()>
fn fcntl_setfd(&mut self, fd: Fd, flags: EnumSet<FdFlag>) -> Result<()>
Source§fn isatty(&self, fd: Fd) -> bool
fn isatty(&self, fd: Fd) -> bool
Source§fn read(&mut self, fd: Fd, buffer: &mut [u8]) -> Result<usize>
fn read(&mut self, fd: Fd, buffer: &mut [u8]) -> Result<usize>
Source§fn write(&mut self, fd: Fd, buffer: &[u8]) -> Result<usize>
fn write(&mut self, fd: Fd, buffer: &[u8]) -> Result<usize>
Source§fn lseek(&mut self, fd: Fd, position: SeekFrom) -> Result<u64>
fn lseek(&mut self, fd: Fd, position: SeekFrom) -> Result<u64>
Source§fn fdopendir(&mut self, fd: Fd) -> Result<Box<dyn Dir>>
fn fdopendir(&mut self, fd: Fd) -> Result<Box<dyn Dir>>
Source§fn opendir(&mut self, path: &CStr) -> Result<Box<dyn Dir>>
fn opendir(&mut self, path: &CStr) -> Result<Box<dyn Dir>>
Source§fn validate_signal(&self, number: RawNumber) -> Option<(Name, Number)>
fn validate_signal(&self, number: RawNumber) -> Option<(Name, Number)>
Source§fn signal_number_from_name(&self, name: Name) -> Option<Number>
fn signal_number_from_name(&self, name: Name) -> Option<Number>
Source§fn sigmask(
&mut self,
op: Option<(SigmaskOp, &[Number])>,
old_mask: Option<&mut Vec<Number>>,
) -> Result<()>
fn sigmask( &mut self, op: Option<(SigmaskOp, &[Number])>, old_mask: Option<&mut Vec<Number>>, ) -> Result<()>
Source§fn get_sigaction(&self, signal: Number) -> Result<Disposition>
fn get_sigaction(&self, signal: Number) -> Result<Disposition>
Source§fn sigaction(
&mut self,
signal: Number,
action: Disposition,
) -> Result<Disposition>
fn sigaction( &mut self, signal: Number, action: Disposition, ) -> Result<Disposition>
Source§fn caught_signals(&mut self) -> Vec<Number>
fn caught_signals(&mut self) -> Vec<Number>
Source§fn kill(
&mut self,
target: Pid,
signal: Option<Number>,
) -> FlexFuture<Result<()>> ⓘ
fn kill( &mut self, target: Pid, signal: Option<Number>, ) -> FlexFuture<Result<()>> ⓘ
Source§fn raise(&mut self, signal: Number) -> FlexFuture<Result<()>> ⓘ
fn raise(&mut self, signal: Number) -> FlexFuture<Result<()>> ⓘ
Source§fn select(
&mut self,
readers: &mut Vec<Fd>,
writers: &mut Vec<Fd>,
timeout: Option<Duration>,
signal_mask: Option<&[Number]>,
) -> Result<c_int>
fn select( &mut self, readers: &mut Vec<Fd>, writers: &mut Vec<Fd>, timeout: Option<Duration>, signal_mask: Option<&[Number]>, ) -> Result<c_int>
Source§fn getsid(&self, pid: Pid) -> Result<Pid>
fn getsid(&self, pid: Pid) -> Result<Pid>
Source§fn setpgid(&mut self, pid: Pid, pgid: Pid) -> Result<()>
fn setpgid(&mut self, pid: Pid, pgid: Pid) -> Result<()>
Source§fn tcgetpgrp(&self, fd: Fd) -> Result<Pid>
fn tcgetpgrp(&self, fd: Fd) -> Result<Pid>
Source§fn tcsetpgrp(&mut self, fd: Fd, pgid: Pid) -> Result<()>
fn tcsetpgrp(&mut self, fd: Fd, pgid: Pid) -> Result<()>
Source§fn new_child_process(&mut self) -> Result<ChildProcessStarter>
fn new_child_process(&mut self) -> Result<ChildProcessStarter>
Source§fn wait(&mut self, target: Pid) -> Result<Option<(Pid, ProcessState)>>
fn wait(&mut self, target: Pid) -> Result<Option<(Pid, ProcessState)>>
Source§fn execve(
&mut self,
path: &CStr,
args: &[CString],
envs: &[CString],
) -> FlexFuture<Result<Infallible>> ⓘ
fn execve( &mut self, path: &CStr, args: &[CString], envs: &[CString], ) -> FlexFuture<Result<Infallible>> ⓘ
Source§fn exit(&mut self, exit_status: ExitStatus) -> FlexFuture<Infallible> ⓘ
fn exit(&mut self, exit_status: ExitStatus) -> FlexFuture<Infallible> ⓘ
Source§fn getpwnam_dir(&self, name: &CStr) -> Result<Option<PathBuf>>
fn getpwnam_dir(&self, name: &CStr) -> Result<Option<PathBuf>>
Source§fn confstr_path(&self) -> Result<UnixString>
fn confstr_path(&self) -> Result<UnixString>
$PATH value where all standard utilities are
expected to be found. Read moreSource§fn shell_path(&self) -> CString
fn shell_path(&self) -> CString
Auto Trait Implementations§
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> SystemEx for T
impl<T> SystemEx for T
Source§fn move_fd_internal(&mut self, from: Fd) -> Result<Fd>
fn move_fd_internal(&mut self, from: Fd) -> Result<Fd>
MIN_INTERNAL_FD or larger. Read more