From be217e8f8e989ea65ffaf5a57fd96f53dfc9bae9 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 21 Nov 2019 10:57:04 -0800 Subject: [PATCH] Update from feedback, fix CI issues, update wasi-test --- Cargo.toml | 2 +- lib/wasi-tests/src/lib.rs | 11 +- lib/wasi/Cargo.toml | 7 +- lib/wasi/src/lib.rs | 19 ++- lib/wasi/src/syscalls/legacy/mod.rs | 1 - lib/wasi/src/syscalls/mod.rs | 1 - src/bin/wasmer.rs | 231 ++++++++++++++-------------- 7 files changed, 142 insertions(+), 130 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3d0c6b7ad..41c17719d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,8 +58,8 @@ members = [ "lib/wasi-tests", "lib/emscripten-tests", "lib/middleware-common-tests", - "examples/plugin-for-example", "examples/parallel", + "examples/plugin-for-example", "examples/parallel-guest", ] diff --git a/lib/wasi-tests/src/lib.rs b/lib/wasi-tests/src/lib.rs index 4508e432e..dba6298a7 100644 --- a/lib/wasi-tests/src/lib.rs +++ b/lib/wasi-tests/src/lib.rs @@ -16,7 +16,13 @@ fn serializing_works() { b"GOROOT=$HOME/.cargo/bin".into_iter().cloned().collect(), ]; let wasm_binary = include_bytes!("../wasitests/fd_read.wasm"); - let import_object = generate_import_object( + let module = compile(&wasm_binary[..]) + .map_err(|e| format!("Can't compile module: {:?}", e)) + .unwrap(); + + let wasi_version = get_wasi_version(&module).expect("WASI module"); + let import_object = generate_import_object_for_version( + wasi_version, args.clone(), envs.clone(), vec![], @@ -25,9 +31,6 @@ fn serializing_works() { std::path::PathBuf::from("wasitests/test_fs/hamlet"), )], ); - let module = compile(&wasm_binary[..]) - .map_err(|e| format!("Can't compile module: {:?}", e)) - .unwrap(); let state_bytes = { let instance = module.instantiate(&import_object).unwrap(); diff --git a/lib/wasi/Cargo.toml b/lib/wasi/Cargo.toml index e413c313e..d81e5e895 100644 --- a/lib/wasi/Cargo.toml +++ b/lib/wasi/Cargo.toml @@ -20,9 +20,4 @@ serde = { version = "1", features = ["derive"] } wasmer-runtime-core = { path = "../runtime-core", version = "0.10.1" } [target.'cfg(windows)'.dependencies] -winapi = "0.3" - -[features] -# Enable support for the older snapshot0 WASI modules -snapshot0 = [] -default = ["snapshot0"] \ No newline at end of file +winapi = "0.3" \ No newline at end of file diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index c0bb562de..ca439bfdb 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -130,9 +130,24 @@ pub fn generate_import_object( } } -#[cfg(feature = "snapshot0")] +/// Creates a Wasi [`ImportObject`] with [`WasiState`] for the given [`WasiVersion`]. +pub fn generate_import_object_for_version( + version: WasiVersion, + args: Vec>, + envs: Vec>, + preopened_files: Vec, + mapped_dirs: Vec<(String, PathBuf)>, +) -> ImportObject { + match version { + WasiVersion::Snapshot0 => { + generate_import_object_snapshot0(args, envs, preopened_files, mapped_dirs) + } + WasiVersion::Snapshot1 => generate_import_object(args, envs, preopened_files, mapped_dirs), + } +} + /// Creates a legacy Wasi [`ImportObject`] with [`WasiState`]. -pub fn generate_import_object_snapshot0( +fn generate_import_object_snapshot0( args: Vec>, envs: Vec>, preopened_files: Vec, diff --git a/lib/wasi/src/syscalls/legacy/mod.rs b/lib/wasi/src/syscalls/legacy/mod.rs index 94e713b23..62cc08f9e 100644 --- a/lib/wasi/src/syscalls/legacy/mod.rs +++ b/lib/wasi/src/syscalls/legacy/mod.rs @@ -2,5 +2,4 @@ //! //! If you are relying on legacy WASI, please upgrade for the best experience. -#[cfg(feature = "snapshot0")] pub mod snapshot0; diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 3cf8d22b7..af6ccab26 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -5,7 +5,6 @@ pub mod unix; #[cfg(any(target_os = "windows"))] pub mod windows; -#[cfg(any(feature = "snapshot0"))] pub mod legacy; use self::types::*; diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index ff8cc8841..03c66a26f 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -26,7 +26,7 @@ use wasmer_clif_backend::CraneliftCompiler; use wasmer_llvm_backend::{LLVMCompiler, LLVMOptions}; use wasmer_runtime::{ cache::{Cache as BaseCache, FileSystemCache, WasmHash}, - Func, Value, VERSION, + Value, VERSION, }; #[cfg(feature = "managed")] use wasmer_runtime_core::tiering::{run_tiering, InteractiveShellContext, ShellExitOperation}; @@ -41,25 +41,6 @@ use wasmer_singlepass_backend::SinglePassCompiler; #[cfg(feature = "wasi")] use wasmer_wasi; -// stub module to make conditional compilation happy -#[cfg(not(feature = "wasi"))] -mod wasmer_wasi { - use wasmer_runtime_core::{import::ImportObject, module::Module}; - - pub fn is_wasi_module(_module: &Module) -> bool { - false - } - - pub fn generate_import_object( - _args: Vec>, - _envs: Vec>, - _preopened_files: Vec, - _mapped_dirs: Vec<(String, std::path::PathBuf)>, - ) -> ImportObject { - unimplemented!() - } -} - #[derive(Debug, StructOpt)] #[structopt(name = "wasmer", about = "Wasm execution runtime.", author)] /// The options for the wasmer Command Line Interface @@ -308,6 +289,7 @@ fn get_mapped_dirs(input: &[String]) -> Result, String> { Ok(md) } +#[cfg(feature = "wasi")] fn get_env_var_args(input: &[String]) -> Result, String> { let mut ev = vec![]; for entry in input.iter() { @@ -323,11 +305,111 @@ fn get_env_var_args(input: &[String]) -> Result, String> { Ok(ev) } +/// Helper function for `execute_wasm` (the `Run` command) +#[cfg(feature = "wasi")] +fn execute_wasi( + wasi_version: wasmer_wasi::WasiVersion, + options: &Run, + env_vars: Vec<(&str, &str)>, + module: wasmer_runtime_core::Module, + mapped_dirs: Vec<(String, PathBuf)>, +) -> Result<(), String> { + let args = if let Some(cn) = &options.command_name { + [cn.clone()] + } else { + [options.path.to_str().unwrap().to_owned()] + } + .iter() + .chain(options.args.iter()) + .cloned() + .map(|arg| arg.into_bytes()) + .collect(); + let envs = env_vars + .into_iter() + .map(|(k, v)| format!("{}={}", k, v).into_bytes()) + .collect(); + let preopened_files = options.pre_opened_directories.clone(); + + let import_object = wasmer_wasi::generate_import_object_for_version( + wasi_version, + args, + envs, + preopened_files, + mapped_dirs, + ); + + #[allow(unused_mut)] // mut used in feature + let mut instance = module + .instantiate(&import_object) + .map_err(|e| format!("Can't instantiate WASI module: {:?}", e))?; + + let start: wasmer_runtime::Func<(), ()> = + instance.func("_start").map_err(|e| format!("{:?}", e))?; + + #[cfg(feature = "managed")] + { + let start_raw: extern "C" fn(&mut wasmer_runtime_core::vm::Ctx) = + unsafe { ::std::mem::transmute(start.get_vm_func()) }; + + unsafe { + run_tiering( + module.info(), + &wasm_binary, + if let Some(ref path) = options.resume { + let mut f = File::open(path).unwrap(); + let mut out: Vec = vec![]; + f.read_to_end(&mut out).unwrap(); + Some( + wasmer_runtime_core::state::InstanceImage::from_bytes(&out) + .expect("failed to decode image"), + ) + } else { + None + }, + &import_object, + start_raw, + &mut instance, + options + .optimized_backends + .iter() + .map(|&backend| -> Box Box + Send> { + Box::new(move || get_compiler_by_backend(backend).unwrap()) + }) + .collect(), + interactive_shell, + )? + }; + } + + #[cfg(not(feature = "managed"))] + { + use wasmer_runtime::error::RuntimeError; + let result = start.call(); + + if let Err(ref err) = result { + match err { + RuntimeError::Trap { msg } => return Err(format!("wasm trap occured: {}", msg)), + #[cfg(feature = "wasi")] + RuntimeError::Error { data } => { + if let Some(error_code) = data.downcast_ref::() { + std::process::exit(error_code.code as i32) + } + } + #[cfg(not(feature = "wasi"))] + RuntimeError::Error { .. } => (), + } + return Err(format!("error: {:?}", err)); + } + } + Ok(()) +} + /// Execute a wasm/wat file fn execute_wasm(options: &Run) -> Result<(), String> { let disable_cache = options.disable_cache; let mapped_dirs = get_mapped_dirs(&options.mapped_dirs[..])?; + #[cfg(feature = "wasi")] let env_vars = get_env_var_args(&options.env_vars[..])?; let wasm_path = &options.path; @@ -582,103 +664,22 @@ fn execute_wasm(options: &Run) -> Result<(), String> { ) .map_err(|e| format!("{:?}", e))?; } else { + #[cfg(feature = "wasi")] let wasi_version = wasmer_wasi::get_wasi_version(&module); - if cfg!(feature = "wasi") && wasi_version.is_some() { - let wasi_version = wasi_version.unwrap(); - let args = if let Some(cn) = &options.command_name { - [cn.clone()] - } else { - [options.path.to_str().unwrap().to_owned()] - } - .iter() - .chain(options.args.iter()) - .cloned() - .map(|arg| arg.into_bytes()) - .collect(); - let envs = env_vars - .into_iter() - .map(|(k, v)| format!("{}={}", k, v).into_bytes()) - .collect(); - let preopened_files = options.pre_opened_directories.clone(); + #[cfg(feature = "wasi")] + let is_wasi = wasi_version.is_some(); + #[cfg(not(feature = "wasi"))] + let is_wasi = false; - let import_object = match wasi_version { - wasmer_wasi::WasiVersion::Snapshot0 => { - wasmer_wasi::generate_import_object_snapshot0( - args, - envs, - preopened_files, - mapped_dirs, - ) - } - wasmer_wasi::WasiVersion::Snapshot1 => { - wasmer_wasi::generate_import_object(args, envs, preopened_files, mapped_dirs) - } - }; - - #[allow(unused_mut)] // mut used in feature - let mut instance = module - .instantiate(&import_object) - .map_err(|e| format!("Can't instantiate WASI module: {:?}", e))?; - - let start: Func<(), ()> = instance.func("_start").map_err(|e| format!("{:?}", e))?; - - #[cfg(feature = "managed")] - { - let start_raw: extern "C" fn(&mut wasmer_runtime_core::vm::Ctx) = - unsafe { ::std::mem::transmute(start.get_vm_func()) }; - - unsafe { - run_tiering( - module.info(), - &wasm_binary, - if let Some(ref path) = options.resume { - let mut f = File::open(path).unwrap(); - let mut out: Vec = vec![]; - f.read_to_end(&mut out).unwrap(); - Some( - wasmer_runtime_core::state::InstanceImage::from_bytes(&out) - .expect("failed to decode image"), - ) - } else { - None - }, - &import_object, - start_raw, - &mut instance, - options - .optimized_backends - .iter() - .map(|&backend| -> Box Box + Send> { - Box::new(move || get_compiler_by_backend(backend).unwrap()) - }) - .collect(), - interactive_shell, - )? - }; - } - - #[cfg(not(feature = "managed"))] - { - use wasmer_runtime::error::RuntimeError; - let result = start.call(); - - if let Err(ref err) = result { - match err { - RuntimeError::Trap { msg } => { - return Err(format!("wasm trap occured: {}", msg)) - } - #[cfg(feature = "wasi")] - RuntimeError::Error { data } => { - if let Some(error_code) = data.downcast_ref::() { - std::process::exit(error_code.code as i32) - } - } - #[cfg(not(feature = "wasi"))] - RuntimeError::Error { .. } => (), - } - return Err(format!("error: {:?}", err)); - } - } + if is_wasi { + #[cfg(feature = "wasi")] + execute_wasi( + wasi_version.unwrap(), + options, + env_vars, + module, + mapped_dirs, + )?; } else { let import_object = wasmer_runtime_core::import::ImportObject::new(); let instance = module