Executables
The executable crate defines the native executable contract and the launcher used across Core.
Role
- Defines
ExecutableTraitand typedGET_MAIN_FUNCTIONcommand contract. - Provides
execute(...)orchestration: permission checks, task spawn, and standard stream propagation.
Boundaries
- In scope: executable ABI contract, launch permission logic, standard stream helper type.
- Out of scope: executable UI/business logic and shell-specific command parsing.
Internal structure
traits.rs:ExecutableTrait,ExecutableWrapper,mount_executables!, command definition.lib.rs: launch path (execute) + execution permission helpers.standard.rs:Standardabstraction (open,duplicate,read_line,close).error.rs: launcher-level error type.
Runtime interaction
- Executables are mounted as character devices exposing
GET_MAIN_FUNCTION. execute(context, path, args, standard, spawner)uses the context's VFS/users/task managers to fetch statistics and check execute permissions.- It opens executable file and requests main function via control command.
- It spawns a task and calls main with
Standardcarrying the same context and the argument vector. - It returns
task::JoinHandle<isize>to allow join/wait by caller.
Dependency model
- Core dependencies: File System, Virtual file system, Task, Users, Shared, Log, Internationalization.
Failure semantics
- Permission denial is explicit (
Error::PermissionDenied). - Missing main entrypoint yields
FailedToGetMainFunction. - Task spawn or VFS failures are mapped into crate error variants.
- Executable runtime errors are converted to negative
isizetask return values in spawned task closure.
Extension points
- New executable crates implement
ExecutableTraitand mount throughExecutableWrapperormount_executables!. buildingfeature gates additional build-time support without changing runtime core path.
Contract vs implementation
- Contract: executable = mounted character device that answers
GET_MAIN_FUNCTIONand receivesStandard + Vec<String>;Standard::contextsupplies explicit capabilities. - Current implementation: launcher uses VFS metadata + users/group checks and task spawn under current task context.
Limitations and trade-offs
ExecutableContext carries task/users/time managers, VFS, optional networking, and optional graphics when the graphics feature is enabled. ExecutableWrapper::new(executable, context) and mount_executables!(context, virtual_file_system, task, ...) bind executables to that context. Standard::open(..., task, virtual_file_system, context) opens streams with the same capability set. Required references are 'static; final binaries own their storage/lifetimes.
- Contract is intentionally narrow (
mainonly), simplifying dispatch but leaving richer lifecycle hooks to higher layers. setuid-style override logic is constrained and permission-checked at launch time.
Exact launch and executable entrypoint contracts
An implementation of ExecutableTrait exposes one static main(Standard<'static>, Vec<String>) -> MainFuture function. MainFuture is a pinned boxed future resolving to Result<(), NonZeroUsize>. ExecutableWrapper<T> owns the implementation value plus a borrowed 'static ExecutableContext, and publishes the GET_MAIN_FUNCTION control command as family b'E', read command 1.
use executable::{ExecutableTrait, MainFuture, Standard};
use alloc::{boxed::Box, string::String, vec::Vec};
struct Example;
impl ExecutableTrait for Example {
fn main(mut standard: Standard<'static>, arguments: Vec<String>) -> MainFuture {
Box::pin(async move {
let _ = arguments;
standard.out().write(b"Hello from Xila\n").await.map_err(|_| {
core::num::NonZeroUsize::new(1).unwrap()
})?;
Ok(())
})
}
}The snippet assumes alloc is available and the program is mounted with a valid ExecutableContext; it illustrates the entrypoint signature rather than a complete runtime launcher.
execute(context, path, arguments, standard, spawner).await looks up VFS statistics, checks execute permissions, opens the character device, obtains the main function, and spawns the program in Task. It returns a JoinHandle<isize>: 0 means success and negative values encode nonzero program errors. Launch/permission failures return executable::Error before a join handle is produced.
Permissions and standard streams
is_execute_allowed checks owner, group and other execution bits; even root does not bypass a file with no execute bits. The set-user-ID override path is intentionally restrictive and can deny unauthorized transitions. Standard carries stdin, stdout, stderr and the ExecutableContext, which supplies Task/Users/Time/VFS and optional Network/Graphics capabilities.
Standard::duplicate() duplicates the three underlying handles, while Standard::close(vfs) closes them. Standard::read_line currently reads one byte at a time, sleeping 10 ms and retrying when a read returns zero. It does not provide general UTF-8 decoding, line-length limits or EOF termination; consumers should not assume an EOF-only input ends that method promptly.
Mounting is done through ExecutableWrapper::new or mount_executables!. The latter removes pre-existing mount entries, mounts the device and sets Permissions::EXECUTABLE. This is a mounted-native-executable protocol, not a general ELF loader and not the Wasmi guest runtime.
Source and API references
libraries/executable/src/traits.rs— command, context, trait and mount macro.libraries/executable/src/lib.rs— permissions and execute.libraries/executable/src/standard.rs— stdio ownership and read behavior.executable::ExecutableTrait— executable entrypoint.