Skip to content
This repository has been archived by the owner on Mar 24, 2022. It is now read-only.

🎬 Add explicit API to run start functions; don't run it implicitly #506

Merged
merged 7 commits into from
Apr 24, 2020

Conversation

acfoltzer
Copy link
Contributor

@acfoltzer acfoltzer commented Apr 24, 2020

Previously, the start function would be implicitly run upon instance creation or resetting. Since the environment can be different at instantiation time to when export functions are typically called (missing embedder contexts, etc), this has tripped people up. It can also just be surprising that any code runs at all at those points, which combined with the inherently confusing nature of Wasm start functions just led to too many messes.

Instance::run_start() is now part of the public API, and will run the start function if it is present in that instance's Wasm module. It does nothing if there is no start function. Instance::run() will now return Err(Error::InstanceNeedsStart) if the start function is present but hasn't been run since the instance was created or reset.

Instance::run_start() will now return an error if run on an instance more than once without an intervening Instance::reset().

If a start function attempts to call a #[lucet_hostcall]-decorated import function, it will be terminated.

This commit bumps the development version to 0.7.0-dev, because while the API changes are semver-compatible, the semantics are not.

Previously, the start function would be implicitly run upon instance creation or resetting. Since
the environment can be different at instantiation time to when export functions are typically
called (missing embedder contexts, etc), this has tripped people up. It can also just be surprising
that any code runs at all at those points, which combined with the inherently confusing nature of
Wasm start functions just led to too many messes.

`Instance::run_start()` is now part of the public API, and will run the start function if it is
present in that instance's Wasm module. It does nothing if there is no start
function. `Instance::run()` will now return `Err(Error::InstanceNeedsStart)` if the start function
is present but hasn't been run since the instance was created or reset.

This commit bumps the development version to `0.7.0-dev`, because while the API changes are
semver-compatible, the semantics are not.
Comment on lines +132 to +136
/// This is `true` if and only if this handle was referenced through the start section.
///
/// The same function may be referenced via other contexts, and will appear with `false` in this
/// field in those cases.
pub is_start_func: bool,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little weird; I could be convinced this belongs in lucet-runtime-internals only, but since FunctionHandle is only used downstream of lucet-module it seemed okay.

///
/// [run]: struct.Instance.html#method.run
/// [start]: https://webassembly.github.io/spec/core/syntax/modules.html#syntax-start
pub fn run_start(&mut self) -> Result<(), Error> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should run_start return an error if it has already been run and the instance not reset? I don't think it's terribly likely to have been calling the start function manually before, so accidentally rerunning it was unlikely, but double-initialization seems more likely with this as public API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I actually was just thinking this. Good call

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocking concern, just a question that I'm curious about: would it be feasible to return an error if any exports are called on an instance before its start function has run?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 21a8ff3

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocking concern, just a question that I'm curious about: would it be feasible to return an error if any exports are called on an instance before its start function has run?

Aaa, race condition on the comments, sorry. This is a good idea; I will add it while my brain is in this corner of the project.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sunfishcode your suggestion is implemented in 50f808f. Thank you!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I read the patch right, it's issuing an error if the start function calls any imports. My question was about issuing errors if any exported function in a module is called before the module's start function is called, which isn't normally possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I definitely read that wrong, whoops. Yes, an error is returned if you try to call any other entrypoints before running the start function, if it exists.

Should I keep the terminate-on-import-function behavior? Now that I'm looking at the spec again I can't actually figure out whether import functions can be called in the start section.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imports can be called from the start function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where's my dunce cap emoji? Reverted in 1e84d31

@acfoltzer
Copy link
Contributor Author

There is now a fair amount of whitespace diff in the start test suite. When reviewing, I recommend filtering that out:

image

Copy link
Member

@cratelyn cratelyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@acfoltzer acfoltzer merged commit 3a8dc71 into master Apr 24, 2020
@acfoltzer acfoltzer deleted the acf/explicit-start branch April 24, 2020 19:33
sunfishcode added a commit to sunfishcode/wasmtime that referenced this pull request May 18, 2020
This also separates instantiation from initialization in a manner
similar to bytecodealliance/lucet#506.
sunfishcode added a commit to sunfishcode/wasmtime that referenced this pull request May 18, 2020
This also separates instantiation from initialization in a manner
similar to bytecodealliance/lucet#506.
sunfishcode added a commit to sunfishcode/wasmtime that referenced this pull request May 21, 2020
This also separates instantiation from initialization in a manner
similar to bytecodealliance/lucet#506.
sunfishcode added a commit to sunfishcode/wasmtime that referenced this pull request May 22, 2020
This also separates instantiation from initialization in a manner
similar to bytecodealliance/lucet#506.
alexcrichton pushed a commit to bytecodealliance/wasmtime that referenced this pull request May 26, 2020
* Reactor support.

This implements the new WASI ABI described here:

https://github.com/WebAssembly/WASI/blob/master/design/application-abi.md

It adds APIs to `Instance` and `Linker` with support for running
WASI programs, and also simplifies the process of instantiating
WASI API modules.

This currently only includes Rust API support.

* Add comments and fix a typo in a comment.

* Fix a rustdoc warning.

* Tidy an unneeded `mut`.

* Factor out instance initialization with `NewInstance`.

This also separates instantiation from initialization in a manner
similar to bytecodealliance/lucet#506.

* Update fuzzing oracles for the API changes.

* Remove `wasi_linker` and clarify that Commands/Reactors aren't connected to WASI.

* Move Command/Reactor semantics into the Linker.

* C API support.

* Fix fuzzer build.

* Update usage syntax from "::" to "=".

* Remove `NewInstance` and `start()`.

* Elaborate on Commands and Reactors and add a spec link.

* Add more comments.

* Fix wat syntax.

* Fix wat.

* Use the `Debug` formatter to format an anyhow::Error.

* Fix wat.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants