-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reactor support. #1565
Reactor support. #1565
Conversation
Subscribe to Label Actioncc @kubkon, @peterhuene
This issue or pull request has been labeled: "wasi", "wasmtime", "wasmtime:api", "wasmtime:docs"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
crates/api/src/instance.rs
Outdated
/// the initialized `Instance` is returned. | ||
/// | ||
/// [WASI ABI initialization]: https://github.com/WebAssembly/WASI/blob/master/design/application-abi.md#current-unstable-abi | ||
pub fn new_wasi_abi(module: &Module, imports: &[Extern]) -> Result<Option<Instance>, Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this API makes sense given WASI today, but this feels sort of uncomfortable. This means that we're splitting the world between "instantiate this module" and "instantiate this wasi module". These constructor semantics need to be bubbled to all callers and such.
Would it be possible to avoid splitting into two worlds? One option might be to have this instead of a constructor:
impl Instance {
fn initialize_wasi(self) -> Result<Option<Instance>, Error> {
// ...
}
}
That way you'd always create the Instance
the same way and it's up to you what to do with it after that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm imagining new_wasi_abi
will be a common case. The name is perhaps confusing because this doesn't mean "run with all the WASI APIs available", but just "run the WASI startup functions if present". I actually wonder if we should rename this to new
and rename the current new
to new_raw
or something, to emphasize that it's not automatically running the WASI startup functions (though it does still run the wasm start function).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally still feel that this is not the API we want. Adding a new constructor for instances which "does the wasi thing" is infectious and will continue to force us to duplicate API surface area into the future. I feel remembering to call new_wasi_abi
is basically equivalent to remembering to call initialize_wasi
, and in terms of composability I feel that an explicit function to initialize is more convenient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lucet change to disconnect initialization from instantiation also points in this direction.
I experimented with a few different API approaches to this, and came up with the patch that's now pushed here. With this, the Rust API's Instance::new
and Linker::instantiate
return a NewInstance
, which is a wrapper around Instance
where the programmer has to initialize it before getting the Instance
out. We may need to do something different for the C API though.
Subscribe to Label Actioncc @peterhuene
This issue or pull request has been labeled: "wasmtime:c-api"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
I do like this approach better myself, but I feel like it's still a bit too heavyweight because it makes I realize it can be a small footgun if these methods are added directly to |
They aren't really WASI-specific. I expect that between the linking spec and interface types, the definition of commands and reactors will eventually want to move out of WASI and into one of those other specs. Would it help if we moved the definition into tool-conventions for now? We could then avoid calling these "WASI" functions. Would that help avoid confusion? I'm also not tied to the name |
Subscribe to Label Actioncc @fitzgen
This issue or pull request has been labeled: "fuzzing"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
Oh sorry, so I mean to say that the current as-is state of
There's not really an easy option for "just give me the This is why I still think it's best to return an work with an |
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.
This also separates instantiation from initialization in a manner similar to bytecodealliance/lucet#506.
Ok, I've now gone back to The new approach now adds a new function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I think the usage of Linker
here is pretty slick.
Would it be possible to add some API-level tests for the new Linker
methods too?
/// | ||
/// An export with an empty string is considered to be a "default export". | ||
/// "_start" is also recognized for compatibility. | ||
pub fn get_default(&self, module: &str) -> Result<Func> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function feels a bit odd to me because the notion of a "default" export doesn't seems super well defined. Is there WASI documentation this could link to?
In isolation it seems like this API should be on an Instance
as well, but I understand why it's here instead of instances at this time. Perhaps they could share an implementation of sorts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also since this is WASI-specific would it make sense to do something like get_wasi_default()
?
@@ -270,6 +271,117 @@ impl Linker { | |||
Ok(self) | |||
} | |||
|
|||
/// Define automatic instantiations of a [`Module`] in this linker. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should highlight very clearly that that the major purpose of this method is to transparently handle WASI conventions as well, e.g. "WASI" should be somewhere in this heading.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm actually trying to de-emphasize "WASI" here. Commands and Reactors are currently defined in a WASI-repository page, but they're not related to WASI APIs, and I expect they'll eventually move out into the linking and/or interface-types specs.
} | ||
|
||
fn handle_module(&self, store: &Store, module_registry: &ModuleRegistry) -> Result<()> { | ||
fn load_main_module(&self, linker: &mut Linker) -> Result<()> { | ||
if let Some(timeout) = self.wasm_timeout { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a "preexisting" bug but we should probably at some point spawn this thread before we start instantiating anything to account for start
functions and _initialize
and such.
(although ideally still discounting compile times of Module
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, not something to handle in this PR, just a thought.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Perhaps, if caching is enabled and a timeout is requested, we can prime the cache with module compilations, and then start the timer before we start the Linker
. If caching is disabled, then we just count compilation time toward the timeout, perhaps.
// Use "" as a default module name. | ||
let module = Module::from_file(linker.store(), &self.module)?; | ||
linker | ||
.module("", &module) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While probably not a huge issue it's a bit odd that we have to assign a name to the instance here, since ideally we'd pull out an instance and "do the wasi thing" on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used a name here because I think src/commands/run.rs shouldn't be pulling out the instance and doing the initialization manually. The Linker
handles that for it, which is good because then the functionality is available to API users as well as command-line users.
Ok this all looks great to me, thanks again for this @sunfishcode! I feel like anything further we can continue to iterate on in-tree if necessary, so I'm gonna merge. |
This implements the new WASI ABI described here:
https://github.com/WebAssembly/WASI/blob/master/design/application-abi.md
It adds APIs to
Instance
andLinker
with support for runningWASI programs, and also simplifies the process of instantiating
WASI API modules.
This currently only includes Rust API support.