Skip to content
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

Reentrant/cyclic calls from host functions? #1364

Closed
Rochet2 opened this issue Apr 7, 2020 · 8 comments
Closed

Reentrant/cyclic calls from host functions? #1364

Rochet2 opened this issue Apr 7, 2020 · 8 comments
Labels
❓ question I've a question!

Comments

@Rochet2
Copy link

Rochet2 commented Apr 7, 2020

Summary

Does wasmer support cyclical/reentrant calls back to module from a host function?

Additional details

I could not find information about if this is supported.
For example a module calls a host function, which then calls a function from the same module.

module---->native
^               |
|               |
-----------------
@Rochet2 Rochet2 added the ❓ question I've a question! label Apr 7, 2020
@Hywan
Copy link
Contributor

Hywan commented Apr 7, 2020

Not tested, but I would say yes :-). What's your usecase?

@Rochet2
Copy link
Author

Rochet2 commented Apr 7, 2020

Basically using WASM for scripting.
Different events call WASM functions.
WASM can call exposed API to affect a game world.
The API can trigger events that then call back to WASM.

For example lets say an event triggers a WASM function and in it you call SpawnCreature function from WASM that adds a new creature into the game world. Then inside that same call an event for the creature's AI initialisation would trigger a call from the native code back to WASM again. Once the whole call sequence created from events ends we return back to where the SpawnCreature function was called from.

So event triggers a call from native to module and module calls a native function that then causes another event that triggers a call from native to module. And eventually the call stack unwinds back to the first call.

@Rochet2
Copy link
Author

Rochet2 commented Apr 7, 2020

I am asking because it is not obvious that it would be supported.
For example I believe this commit implemented similar support for wasmtime a month ago if I am not mistaken: bytecodealliance/wasmtime@ca9f33b

@Rochet2 Rochet2 changed the title Cyclical calls? Reentrant/cyclic calls from host functions? Apr 7, 2020
@MarkMcCaskey
Copy link
Contributor

MarkMcCaskey commented Apr 7, 2020

Yes, this has been possible with Wasmer, but it's not very simple to do right now: you can't get an Instance from a Ctx, so calling directly is not very simple. It should be possible to store the DynFunc or Func ahead of time though. Doing it more dynamically would require unsafe I believe...

We should investigate improving the API here. We also support calling "function pointers" on the host when passed from the guest (this happens through the table) and we have an example of it somewhere but it's not well documented. I'll update this comment in a bit with the information!

@webmaster128
Copy link
Contributor

webmaster128 commented Apr 8, 2020

Ah, funny: I tried the same thing yesterday/today and gave up at some point. My flow was

   Wasm    --call "read_db" import (1)-->  Wasm  ---get data (2)-->  Data
 Contract  <-----return read_db (6)------   VM   <------(3)--------  Base
 ^   ^                                     | |      
 |   |                                     | |   
 |   --call "allocate" export (4)----------| |
 |-------------write result (5)--------------|

In CosmWasm/cosmwasm#245 you find all the pointer magic, which basically is a raw way of creating a weak pointer stored in the Ctx to its parent Instance.

This way, I can call let _context = instance.context(); via ctx fron the import implementation, but let func = match instance.func(name) crashes.

@reuvenpo
Copy link

reuvenpo commented Apr 26, 2020

While digging around the code for wasmer-runtime-core v0.16.2 I noticed that the
Ctx type has a field module of type
*const ModuleInner that has a field runnable_module of type
Arc<Box<dyn RunnableModule>>, and that trait inside has a method:
get_func(&self, info: &ModuleInfo, local_func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>>.
That type vm::Func has no methods but is a pointer to the functions that the module exports, and is a field in the Func type that is normally used for invoking functions in the wasm runtime.
The ModuleInfo can be found through the info field on Ctx's module field.

To summarize the above, from the context of a host function, an exported function pointer is available through:

let module: &ModuleInner = unsafe { &*context.module };
let fn_ptr = module.runnable_module.get_func(&module.info, LocalFuncIndex::new(/* index */));

Given that these pointers are already available, Is it possible to also contain the rest of the metadata that would be required to create and invoke the functions themselves?

Alternatively, would it be possible to just include a *mut Instance to the instance that governs the host functions runtime, analgously to a &mut self pointer, much like the above suggestion?

@mikevoronov
Copy link
Contributor

mikevoronov commented Jun 11, 2020

@Rochet2 with making Func::from_raw_parts pub this approach could be used to call export functions from import. Based on this. To test you could use this version of Wasmer (branch fluence) with Func::from_raw_parts public.

@Rochet2
Copy link
Author

Rochet2 commented Jul 7, 2020

The original question was answered. I am closing this in favor of #638 which seems to discuss the lack of API for calling functions from host functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
❓ question I've a question!
Projects
None yet
Development

No branches or pull requests

6 participants