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