Skip to content

Commit

Permalink
Merge branch 'master' into fix-vm-leak
Browse files Browse the repository at this point in the history
  • Loading branch information
Hywan committed Nov 26, 2020
2 parents 286426a + 29eef4f commit 85ae8c7
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

### Changed

- [#1838](https://github.com/wasmerio/wasmer/pull/1838) Deprecate `WasiEnv::state_mut`: prefer `WasiEnv::state` instead.
- [#1663](https://github.com/wasmerio/wasmer/pull/1663) Function environments passed to host functions now must be passed by `&` instead of `&mut`. This is a breaking change. This change fixes a race condition when a host function is called from multiple threads. If you need mutability in your environment, consider using `std::sync::Mutex` or other synchronization primitives.
- [#1830](https://github.com/wasmerio/wasmer/pull/1830) Minimum supported Rust version bumped to 1.47.0
- [#1810](https://github.com/wasmerio/wasmer/pull/1810) Make the `state` field of `WasiEnv` public
Expand Down
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,8 @@ required-features = ["cranelift"]
name = "imported-function-env"
path = "examples/imports_function_env.rs"
required-features = ["cranelift"]

[[example]]
name = "hello-world"
path = "examples/hello_world.rs"
required-features = ["cranelift"]
20 changes: 17 additions & 3 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,21 @@ example.

### Basics

1. [**Instantiating a module**][instance], explains the basics of using Wasmer
1. [**Hello World**][hello-world], explains the core concepts of the Wasmer
API for compiling and executing WebAssembly.

_Keywords_: introduction, instance, module.

<details>
<summary><em>Execute the example</em></summary>

```shell
$ cargo run --example hello-world --release --features "cranelift"
```

</details>

2. [**Instantiating a module**][instance], explains the basics of using Wasmer
and how to create an instance out of a Wasm module.

_Keywords_: instance, module.
Expand All @@ -53,7 +67,7 @@ example.

</details>

2. [**Handling errors**][errors], explains the basics of interacting with
3. [**Handling errors**][errors], explains the basics of interacting with
Wasm module memory.

_Keywords_: memory, module.
Expand All @@ -67,7 +81,7 @@ example.

</details>

3. [**Interacting with memory**][memory], explains the basics of interacting with
4. [**Interacting with memory**][memory], explains the basics of interacting with
Wasm module memory.

_Keywords_: memory, module.
Expand Down
85 changes: 85 additions & 0 deletions examples/hello_world.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//! This is a simple example introducing the core concepts of the Wasmer API.
//!
//! You can run the example directly by executing the following in the Wasmer root:
//!
//! ```shell
//! cargo run --example hello-world --release --features "cranelift"
//! ```
use wasmer::{imports, wat2wasm, Function, Instance, Module, NativeFunc, Store};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_jit::JIT;

fn main() -> anyhow::Result<()> {
// First we create a simple Wasm program to use with Wasmer.
// We use the WebAssembly text format and use `wasmer::wat2wasm` to compile
// it into a WebAssembly binary.
//
// Most WebAssembly programs come from compiling source code in a high level
// language and will already be in the binary format.
let wasm_bytes = wat2wasm(
br#"
(module
;; First we define a type with no parameters and no results.
(type $no_args_no_rets_t (func (param) (result)))
;; Then we declare that we want to import a function named "env" "say_hello" with
;; that type signature.
(import "env" "say_hello" (func $say_hello (type $no_args_no_rets_t)))
;; Finally we create an entrypoint that calls our imported function.
(func $run (type $no_args_no_rets_t)
(call $say_hello))
;; And mark it as an exported function named "run".
(export "run" (func $run)))
"#,
)?;

// Next we create the `Store`, the top level type in the Wasmer API.
//
// Note that we don't need to specify the engine/compiler if we want to use
// the default provided by Wasmer.
// You can use `Store::default()` for that.
//
// However for the purposes of showing what's happening, we create a compiler
// (`Cranelift`) and pass it to an engine (`JIT`). We then pass the engine to
// the store and are now ready to compile and run WebAssembly!
let store = Store::new(&JIT::new(&Cranelift::default()).engine());
// We then use our store and Wasm bytes to compile a `Module`.
// A `Module` is a compiled WebAssembly module that isn't ready to execute yet.
let module = Module::new(&store, wasm_bytes)?;

// Next we'll set up our `Module` so that we can execute it.

// We define a function to act as our "env" "say_hello" function imported in the
// Wasm program above.
fn say_hello_world() {
println!("Hello, world!")
}

// We then create an import object so that the `Module`'s imports can be satisfied.
let import_object = imports! {
// We use the default namespace "env".
"env" => {
// And call our function "say_hello".
"say_hello" => Function::new_native(&store, say_hello_world),
}
};

// We then use the `Module` and the import object to create an `Instance`.
//
// An `Instance` is a compiled WebAssembly module that has been set up
// and is ready to execute.
let instance = Instance::new(&module, &import_object)?;
// We get the `NativeFunc` with no parameters and no results from the instance.
//
// Recall that the Wasm module exported a function named "run", this is getting
// that exported function from the `Instance`.
let run_func: NativeFunc<(), ()> = instance.exports.get_native_function("run")?;

// Finally, we call our exported Wasm function which will call our "say_hello"
// function and return.
run_func.call()?;

Ok(())
}
12 changes: 11 additions & 1 deletion lib/wasi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ pub enum WasiError {
pub struct WasiEnv {
/// Shared state of the WASI system. Manages all the data that the
/// executing WASI program can see.
///
/// Be careful when using this in host functions that call into Wasm:
/// if the lock is held and the Wasm calls into a host function that tries
/// to lock this mutex, the program will deadlock.
pub state: Arc<Mutex<WasiState>>,
memory: Arc<WasiMemory>,
}
Expand Down Expand Up @@ -163,11 +167,17 @@ impl WasiEnv {
}

/// Get the WASI state
///
/// Be careful when using this in host functions that call into Wasm:
/// if the lock is held and the Wasm calls into a host function that tries
/// to lock this mutex, the program will deadlock.
pub fn state(&self) -> MutexGuard<WasiState> {
self.state.lock().unwrap()
}

/// Get the WASI state (mutable)
// TODO: delete this method before 1.0.0 release
#[doc(hidden)]
#[deprecated(since = "1.0.0-beta1", note = "Please use the `state` method instead")]
pub fn state_mut(&mut self) -> MutexGuard<WasiState> {
self.state.lock().unwrap()
}
Expand Down

0 comments on commit 85ae8c7

Please sign in to comment.