Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Refragg committed Aug 20, 2023
2 parents 1edfdd4 + 8973c18 commit 4bba3b9
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 26 deletions.
2 changes: 1 addition & 1 deletion crates/livesplit-auto-splitting/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ mod settings;
mod timer;

pub use process::Process;
pub use runtime::{CreationError, InterruptHandle, Runtime};
pub use runtime::{Config, CreationError, InterruptHandle, Runtime};
pub use settings::{SettingValue, SettingsStore, UserSetting, UserSettingKind};
pub use time;
pub use timer::{Timer, TimerState};
2 changes: 1 addition & 1 deletion crates/livesplit-auto-splitting/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ impl Process {
}
}

fn build_path(original_path: &Path) -> Option<Box<str>> {
pub fn build_path(original_path: &Path) -> Option<Box<str>> {
let mut path = String::from("/mnt");
for component in original_path.components() {
if !path.ends_with('/') {
Expand Down
74 changes: 60 additions & 14 deletions crates/livesplit-auto-splitting/src/runtime.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
#![allow(clippy::unnecessary_cast)]

use crate::{
process::Process, settings::UserSetting, timer::Timer, SettingValue, SettingsStore,
UserSettingKind,
process::{build_path, Process},
settings::UserSetting,
timer::Timer,
SettingValue, SettingsStore, UserSettingKind,
};

use anyhow::{ensure, format_err, Context as _, Result};
use slotmap::{Key, KeyData, SlotMap};
use snafu::Snafu;
use std::{
env::consts::{ARCH, OS},
path::PathBuf,
path::{Path, PathBuf},
str,
time::{Duration, Instant},
};
use sysinfo::{ProcessExt, ProcessRefreshKind, RefreshKind, System, SystemExt};
use wasi_common::{dir::DirCaps, file::FileCaps};
use wasmtime::{
Caller, Config, Engine, Extern, Linker, Memory, Module, OptLevel, Store, TypedFunc,
Caller, Engine, Extern, Linker, Memory, Module, OptLevel, Store, TypedFunc,
WasmBacktraceDetails,
};
use wasmtime_wasi::{ambient_authority, WasiCtx, WasiCtxBuilder};

Expand Down Expand Up @@ -153,6 +156,41 @@ impl ProcessList {
}
}

/// The configuration to use when creating a new [`Runtime`].
#[non_exhaustive]
pub struct Config<'a> {
/// The settings store that is used to store the settings of the auto
/// splitter. This contains all the settings that are currently modified by
/// the user. It may not contain all the settings that are registered as
/// user settings, because the user may not have modified them yet.
pub settings_store: Option<SettingsStore>,
/// The auto splitter itself may be a runtime that wants to load a script
/// from a file to interpret. This is the path to that script. It is
/// provided to the auto splitter as the `SCRIPT_PATH` environment variable.
/// **This is currently experimental and may change in the future.**
pub interpreter_script_path: Option<&'a Path>,
/// This enables debug information for the WebAssembly module. This is
/// useful for debugging purposes, but due to bugs in wasmtime might
/// currently crash the runtime. This is disabled by default. Relevant
/// issue: https://github.com/bytecodealliance/wasmtime/issues/3999
pub debug_info: bool,
/// This enables backtrace details for the WebAssembly module. If a trap
/// occurs more details are printed in the backtrace. This is enabled by
/// default.
pub backtrace_details: bool,
}

impl Default for Config<'_> {
fn default() -> Self {
Self {
settings_store: None,
interpreter_script_path: None,
debug_info: false,
backtrace_details: true,
}
}
}

/// An auto splitter runtime that allows using an auto splitter provided as a
/// WebAssembly module to control a timer.
pub struct Runtime<T: Timer> {
Expand All @@ -165,14 +203,16 @@ pub struct Runtime<T: Timer> {
impl<T: Timer> Runtime<T> {
/// Creates a new runtime with the given path to the WebAssembly module and
/// the timer that the module then controls.
pub fn new(
module: &[u8],
timer: T,
settings_store: SettingsStore,
) -> Result<Self, CreationError> {
pub fn new(module: &[u8], timer: T, config: Config<'_>) -> Result<Self, CreationError> {
let engine = Engine::new(
Config::new()
wasmtime::Config::new()
.cranelift_opt_level(OptLevel::Speed)
.debug_info(config.debug_info)
.wasm_backtrace_details(if config.backtrace_details {
WasmBacktraceDetails::Enable
} else {
WasmBacktraceDetails::Disable
})
.epoch_interruption(true),
)
.map_err(|source| CreationError::EngineCreation { source })?;
Expand All @@ -185,12 +225,12 @@ impl<T: Timer> Runtime<T> {
Context {
processes: SlotMap::with_key(),
user_settings: Vec::new(),
settings_store,
settings_store: config.settings_store.unwrap_or_default(),
tick_rate: Duration::new(0, 1_000_000_000 / 120),
timer,
memory: None,
process_list: ProcessList::new(),
wasi: build_wasi(),
wasi: build_wasi(config.interpreter_script_path),
},
);

Expand Down Expand Up @@ -304,8 +344,14 @@ impl<T: Timer> Runtime<T> {
}
}

fn build_wasi() -> WasiCtx {
let wasi = WasiCtxBuilder::new().build();
fn build_wasi(script_path: Option<&Path>) -> WasiCtx {
let mut wasi = WasiCtxBuilder::new().build();

if let Some(script_path) = script_path {
if let Some(path) = build_path(script_path) {
let _ = wasi.push_env("SCRIPT_PATH", &path);
}
}

#[cfg(windows)]
{
Expand Down
4 changes: 2 additions & 2 deletions crates/livesplit-auto-splitting/tests/sandboxing.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use livesplit_auto_splitting::{Runtime, SettingsStore, Timer, TimerState};
use livesplit_auto_splitting::{Config, Runtime, SettingsStore, Timer, TimerState};
use std::{
ffi::OsStr,
fmt, fs,
Expand Down Expand Up @@ -64,7 +64,7 @@ fn compile(crate_name: &str) -> anyhow::Result<Runtime<DummyTimer>> {
Ok(Runtime::new(
&std::fs::read(wasm_path).unwrap(),
DummyTimer,
SettingsStore::new(),
Config::default(),
)?)
}

Expand Down
16 changes: 8 additions & 8 deletions src/auto_splitting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@

use crate::timing::{SharedTimer, TimerPhase};
use livesplit_auto_splitting::{
CreationError, InterruptHandle, Runtime as ScriptRuntime, Timer as AutoSplitTimer, TimerState,
Config, CreationError, InterruptHandle, Runtime as ScriptRuntime, Timer as AutoSplitTimer,
TimerState,
};
pub use livesplit_auto_splitting::{SettingValue, SettingsStore, UserSetting, UserSettingKind};
use snafu::Snafu;
Expand Down Expand Up @@ -513,7 +514,7 @@ async fn run(
let mut runtime = loop {
match receiver.recv().await {
Some(Request::LoadScript(script, ret)) => {
match ScriptRuntime::new(&script, Timer(timer.clone()), SettingsStore::new()) {
match ScriptRuntime::new(&script, Timer(timer.clone()), Config::default()) {
Ok(r) => {
ret.send(Ok(())).ok();
script_path = script;
Expand Down Expand Up @@ -559,11 +560,7 @@ async fn run(
match timeout_at(next_step, receiver.recv()).await {
Ok(Some(request)) => match request {
Request::LoadScript(script, ret) => {
match ScriptRuntime::new(
&script,
Timer(timer.clone()),
SettingsStore::new(),
) {
match ScriptRuntime::new(&script, Timer(timer.clone()), Config::default()) {
Ok(r) => {
ret.send(Ok(())).ok();
runtime = r;
Expand All @@ -582,10 +579,13 @@ async fn run(
continue 'back_to_not_having_a_runtime;
}
Request::ReloadScript(ret) => {

Check failure on line 581 in src/auto_splitting/mod.rs

View workflow job for this annotation

GitHub Actions / Check formatting

Diff in /home/runner/work/livesplit-core/livesplit-core/src/auto_splitting/mod.rs
let mut config = Config::default();
config.settings_store = Some(runtime.settings_store().clone());

match ScriptRuntime::new(
&script_path,
Timer(timer.clone()),
runtime.settings_store().clone(),
config,
) {
Ok(r) => {
ret.send(Ok(())).ok();
Expand Down
3 changes: 3 additions & 0 deletions src/platform/normal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ cfg_if::cfg_if! {
// defined as a clock measuring real time`, making it sound like a compliant
// implementation should measure the time the OS is suspended as well.
//
// Open issue:
// https://github.com/WebAssembly/wasi-clocks/issues/47
//
// # Web
//
// In the web we use `performance.now()` which they want to specify as being
Expand Down

0 comments on commit 4bba3b9

Please sign in to comment.