mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
Merge #383
383: Hook up wasi exit code to wasmer cli r=lachlansneff a=lachlansneff Test by running: ``` > target/release/wasmer run examples/exit.wat > echo $? ``` should echo "7". Fixes (at least the exit code part) of #361. Co-authored-by: Lachlan Sneff <lachlan.sneff@gmail.com>
This commit is contained in:
commit
f104b2c324
@ -5,6 +5,7 @@ All PRs to the Wasmer repository must add to this file.
|
||||
Blocks of changes will separated by version increments.
|
||||
|
||||
## **[Unreleased]**
|
||||
- [#383](https://github.com/wasmerio/wasmer/pull/383) Hook up wasi exit code to wasmer cli.
|
||||
- [#382](https://github.com/wasmerio/wasmer/pull/382) Improve error message on `--backend` flag to only suggest currently enabled backends
|
||||
- [#381](https://github.com/wasmerio/wasmer/pull/381) Allow retrieving propagated user errors.
|
||||
- [#379](https://github.com/wasmerio/wasmer/pull/379) Fix small return types from imported functions.
|
||||
|
11
examples/exit.wat
Normal file
11
examples/exit.wat
Normal file
@ -0,0 +1,11 @@
|
||||
(module
|
||||
(import "wasi_unstable" "proc_exit" (func $proc_exit (param i32)))
|
||||
(export "_start" (func $_start))
|
||||
|
||||
(memory 10)
|
||||
(export "memory" (memory 0))
|
||||
|
||||
(func $_start
|
||||
(call $proc_exit (i32.const 7))
|
||||
)
|
||||
)
|
@ -11,12 +11,15 @@ use std::str::FromStr;
|
||||
use hashbrown::HashMap;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use wasmer::webassembly::InstanceABI;
|
||||
use wasmer::*;
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
#[cfg(feature = "backend:llvm")]
|
||||
use wasmer_llvm_backend::LLVMCompiler;
|
||||
use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH};
|
||||
use wasmer_runtime::{
|
||||
cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH},
|
||||
error::RuntimeError,
|
||||
Func, Value,
|
||||
};
|
||||
use wasmer_runtime_core::{
|
||||
self,
|
||||
backend::{Compiler, CompilerConfig},
|
||||
@ -301,60 +304,81 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
};
|
||||
|
||||
// TODO: refactor this
|
||||
let (abi, import_object, _em_globals) = if wasmer_emscripten::is_emscripten_module(&module) {
|
||||
if wasmer_emscripten::is_emscripten_module(&module) {
|
||||
let mut emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new(&module);
|
||||
(
|
||||
InstanceABI::Emscripten,
|
||||
wasmer_emscripten::generate_emscripten_env(&mut emscripten_globals),
|
||||
Some(emscripten_globals), // TODO Em Globals is here to extend, lifetime, find better solution
|
||||
let import_object = wasmer_emscripten::generate_emscripten_env(&mut emscripten_globals);
|
||||
let mut instance = module
|
||||
.instantiate(&import_object)
|
||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
||||
|
||||
wasmer_emscripten::run_emscripten_instance(
|
||||
&module,
|
||||
&mut instance,
|
||||
if let Some(cn) = &options.command_name {
|
||||
cn
|
||||
} else {
|
||||
options.path.to_str().unwrap()
|
||||
},
|
||||
options.args.iter().map(|arg| arg.as_str()).collect(),
|
||||
)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
} else {
|
||||
if cfg!(feature = "wasi") && wasmer_wasi::is_wasi_module(&module) {
|
||||
(
|
||||
InstanceABI::WASI,
|
||||
wasmer_wasi::generate_import_object(
|
||||
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())
|
||||
let import_object = wasmer_wasi::generate_import_object(
|
||||
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(),
|
||||
env::vars()
|
||||
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
|
||||
.collect(),
|
||||
env::vars()
|
||||
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
|
||||
.collect(),
|
||||
options.pre_opened_directories.clone(),
|
||||
),
|
||||
None,
|
||||
)
|
||||
options.pre_opened_directories.clone(),
|
||||
);
|
||||
|
||||
let instance = module
|
||||
.instantiate(&import_object)
|
||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
||||
|
||||
let start: Func<(), ()> = instance.func("_start").map_err(|e| format!("{:?}", e))?;
|
||||
|
||||
let result = start.call();
|
||||
|
||||
if let Err(ref err) = result {
|
||||
match err {
|
||||
RuntimeError::Trap { msg } => panic!("wasm trap occured: {}", msg),
|
||||
RuntimeError::Error { data } => {
|
||||
if let Some(error_code) = data.downcast_ref::<wasmer_wasi::ExitCode>() {
|
||||
std::process::exit(error_code.code as i32)
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("error: {:?}", err)
|
||||
}
|
||||
} else {
|
||||
(
|
||||
InstanceABI::None,
|
||||
wasmer_runtime_core::import::ImportObject::new(),
|
||||
None,
|
||||
)
|
||||
let import_object = wasmer_runtime_core::import::ImportObject::new();
|
||||
let instance = module
|
||||
.instantiate(&import_object)
|
||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
||||
|
||||
let args: Vec<Value> = options
|
||||
.args
|
||||
.iter()
|
||||
.map(|arg| arg.as_str())
|
||||
.map(|x| Value::I32(x.parse().unwrap()))
|
||||
.collect();
|
||||
instance
|
||||
.dyn_func("main")
|
||||
.map_err(|e| format!("{:?}", e))?
|
||||
.call(&args)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
}
|
||||
};
|
||||
|
||||
let mut instance = module
|
||||
.instantiate(&import_object)
|
||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
||||
|
||||
webassembly::run_instance(
|
||||
&module,
|
||||
&mut instance,
|
||||
abi,
|
||||
if let Some(cn) = &options.command_name {
|
||||
cn
|
||||
} else {
|
||||
options.path.to_str().unwrap()
|
||||
},
|
||||
options.args.iter().map(|arg| arg.as_str()).collect(),
|
||||
)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -77,40 +77,3 @@ pub fn compile(buffer_source: &[u8]) -> Result<Module> {
|
||||
let module = runtime::compile(buffer_source)?;
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
// /// The same as `compile` but takes a `CompilerConfig` for the purpose of
|
||||
// /// changing the compiler's behavior
|
||||
// pub fn compile_with_config_with(
|
||||
// buffer_source: &[u8],
|
||||
// compiler_config: CompilerConfig,
|
||||
// ) -> Result<Module> {
|
||||
// let module = runtime::compile_with_config(buffer_source, compiler_config)?;
|
||||
// Ok(module)
|
||||
// }
|
||||
|
||||
/// Performs common instance operations needed when an instance is first run
|
||||
/// including data setup, handling arguments and calling a main function
|
||||
pub fn run_instance(
|
||||
module: &Module,
|
||||
instance: &mut Instance,
|
||||
abi: InstanceABI,
|
||||
path: &str,
|
||||
args: Vec<&str>,
|
||||
) -> CallResult<()> {
|
||||
match abi {
|
||||
InstanceABI::Emscripten => {
|
||||
run_emscripten_instance(module, instance, path, args)?;
|
||||
}
|
||||
InstanceABI::WASI => {
|
||||
instance.call("_start", &[])?;
|
||||
}
|
||||
InstanceABI::None => {
|
||||
let args: Vec<Value> = args
|
||||
.into_iter()
|
||||
.map(|x| Value::I32(x.parse().unwrap()))
|
||||
.collect();
|
||||
instance.call("main", &args)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user