pub struct SubprocessExecutor { /* private fields */ }Expand description
Subprocess executor
Manages a child process for executing compiled code with isolation. The subprocess binary implements the IPC protocol for loading libraries and executing functions.
§Why Subprocess? (ODD-0038 Decision 3)
- Rust threads cannot be interrupted (no pthread_cancel)
- Ctrl-C support requires process isolation
- Crashes in user code don’t corrupt REPL state
- evcxr evidence: Subprocess from day one, never changed
§IPC Protocol (ODD-0038 Decision 3a)
Commands (stdin):
LOAD <path>- Load dynamic libraryRUN <cache_key>- Execute function from loaded library
Responses (stdout):
LOADED- Library loaded successfullyOXUR_EXECUTION_COMPLETE- Execution finishedOXUR_RUNTIME_ERROR <msg>- Runtime errorOXUR_PANIC_LOCATION <info>- Panic with location
§Status
Phase 1 STUB: Manages subprocess lifecycle but doesn’t execute yet. Full IPC implementation coming in Phase 2.
§Examples
use oxur_repl::executor::SubprocessExecutor;
use std::path::PathBuf;
// Create executor (spawns subprocess)
let mut executor = SubprocessExecutor::new()?;
// Load a library (Phase 2)
// executor.load_library(&PathBuf::from("path/to/lib.so"))?;
// Execute code (Phase 2)
// let result = executor.execute("cache_key_123")?;
// Shutdown
executor.shutdown()?;Implementations§
Source§impl SubprocessExecutor
impl SubprocessExecutor
Sourcepub fn new() -> Result<Self, ExecutorError>
pub fn new() -> Result<Self, ExecutorError>
Create a new subprocess executor
Spawns the subprocess binary and establishes IPC connection.
§Errors
Returns error if subprocess cannot be spawned
Sourcepub fn is_loaded(&self, cache_key: impl AsRef<str>) -> bool
pub fn is_loaded(&self, cache_key: impl AsRef<str>) -> bool
Check if a library is already loaded
Sourcepub fn load_library(
&mut self,
path: &Path,
cache_key: impl AsRef<str>,
) -> Result<(), ExecutorError>
pub fn load_library( &mut self, path: &Path, cache_key: impl AsRef<str>, ) -> Result<(), ExecutorError>
Load a dynamic library into the subprocess
Sends a LOAD command via IPC and waits for confirmation.
§Arguments
path- Path to dynamic library (.so/.dylib/.dll)cache_key- Cache key for tracking loaded state
§Errors
Returns error if:
- Subprocess is not running
- LOAD command fails to send
- Library fails to load in subprocess
- Response parsing fails
Sourcepub fn execute(
&mut self,
cache_key: impl AsRef<str>,
) -> Result<ExecutionResult, ExecutorError>
pub fn execute( &mut self, cache_key: impl AsRef<str>, ) -> Result<ExecutionResult, ExecutorError>
Execute compiled code from a loaded library
Sends a RUN command via IPC and parses the execution result.
§Arguments
cache_key- Cache key identifying the function to execute
§Errors
Returns error if:
- Subprocess is not running
- RUN command fails to send
- Response parsing fails
§Returns
Returns ExecutionResult with success, runtime error, or panic information
Sourcepub fn shutdown(&mut self) -> Result<Option<ExitStatus>, ExecutorError>
pub fn shutdown(&mut self) -> Result<Option<ExitStatus>, ExecutorError>
Shutdown the subprocess
Closes stdin and waits for subprocess to exit.
Returns the exit status if the subprocess was running, None otherwise.
Sourcepub fn restart(&mut self) -> Result<RestartReason, ExecutorError>
pub fn restart(&mut self) -> Result<RestartReason, ExecutorError>
Restart the subprocess
Useful for recovering from crashes or clearing state. Records the restart reason in metrics based on exit status.
Returns the restart reason determined from exit status.
Sourcepub fn restart_user_requested(&mut self) -> Result<(), ExecutorError>
pub fn restart_user_requested(&mut self) -> Result<(), ExecutorError>
Restart the subprocess due to user request
Records the restart as user-requested in metrics.
Sourcepub fn loaded_count(&self) -> usize
pub fn loaded_count(&self) -> usize
Get count of loaded libraries
Sourcepub fn is_running(&self) -> bool
pub fn is_running(&self) -> bool
Check if subprocess is running
Sourcepub fn uptime_seconds(&self) -> f64
pub fn uptime_seconds(&self) -> f64
Get the current subprocess uptime in seconds
Sourcepub fn restart_count(&self) -> u64
pub fn restart_count(&self) -> u64
Get the total restart count
Sourcepub fn update_metrics(&self)
pub fn update_metrics(&self)
Update the uptime gauge in metrics
Should be called periodically to keep the metrics current.
Sourcepub fn metrics(&self) -> &SubprocessMetrics
pub fn metrics(&self) -> &SubprocessMetrics
Get a reference to the subprocess metrics
Trait Implementations§
Source§impl Debug for SubprocessExecutor
impl Debug for SubprocessExecutor
Auto Trait Implementations§
impl Freeze for SubprocessExecutor
impl RefUnwindSafe for SubprocessExecutor
impl Send for SubprocessExecutor
impl Sync for SubprocessExecutor
impl Unpin for SubprocessExecutor
impl UnwindSafe for SubprocessExecutor
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> 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> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);