Skip to content

Commit bc6fe15

Browse files
authored
Optionally call main() in WASI reactors as a convenience. (proxy-wasm#133)
WASI reactors differ from WASI commands in that they have multiple entrypoints (i.e. proxy_on_* callbacks) instead of only main(). Currently, each Proxy-Wasm SDK uses different approch to startup: - AssemblyScript SDK uses Wasm's start function. - C++ SDK creates WASI reactor with global C++ constructors taking care of early initialization and registration of plugins. - Rust SDK creates Wasm library, and suggests (via examples) using _start() function called at startup to do early initialization. Unfortunately, this is the same function name that WASI commands are using, which means that WASI constructors cannot be injected and executed at startup. - TinyGo SDK creates WASI command and calls main() at startup, but it doesn't exit after main() function returns. Calling main() in WASI reactors would allow us to prepare for when they are stablized in Rust, and to have a non-breaking fallback in case TinyGo decides to exit after main() function returns. Signed-off-by: Piotr Sikora <[email protected]>
1 parent 5ea92c8 commit bc6fe15

File tree

3 files changed

+21
-10
lines changed

3 files changed

+21
-10
lines changed

include/proxy-wasm/wasm.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,10 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
196196
std::unordered_map<std::string, std::string>
197197
envs_; // environment variables passed through wasi.environ_get
198198

199-
WasmCallVoid<0> _initialize_; /* Emscripten v1.39.17+ */
200-
WasmCallVoid<0> _start_; /* Emscripten v1.39.0+ */
201-
WasmCallVoid<0> __wasm_call_ctors_;
199+
WasmCallVoid<0> _initialize_; /* WASI reactor (Emscripten v1.39.17+, Rust nightly) */
200+
WasmCallVoid<0> _start_; /* WASI command (Emscripten v1.39.0+, TinyGo) */
202201

202+
WasmCallWord<2> main_;
203203
WasmCallWord<1> malloc_;
204204

205205
// Calls into the VM.

src/null/null_plugin.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ void NullPlugin::getFunction(std::string_view function_name, WasmCallVoid<0> *f)
3737
*f = nullptr;
3838
} else if (function_name == "_start") {
3939
*f = nullptr;
40-
} else if (function_name == "__wasm_call_ctors") {
41-
*f = nullptr;
4240
} else if (!wasm_vm_->integration()->getNullVmFunction(function_name, false, 0, this, f)) {
4341
error("Missing getFunction for: " + std::string(function_name));
4442
*f = nullptr;
@@ -167,7 +165,9 @@ void NullPlugin::getFunction(std::string_view function_name, WasmCallWord<1> *f)
167165

168166
void NullPlugin::getFunction(std::string_view function_name, WasmCallWord<2> *f) {
169167
auto plugin = this;
170-
if (function_name == "proxy_on_vm_start") {
168+
if (function_name == "main") {
169+
*f = nullptr;
170+
} else if (function_name == "proxy_on_vm_start") {
171171
*f = [plugin](ContextBase *context, Word context_id, Word configuration_size) {
172172
SaveRestoreContext saved_context(context);
173173
return Word(plugin->onStart(context_id, configuration_size));

src/wasm.cc

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,11 @@ void WasmBase::getFunctions() {
147147
#define _GET(_fn) wasm_vm_->getFunction(#_fn, &_fn##_);
148148
#define _GET_ALIAS(_fn, _alias) wasm_vm_->getFunction(#_alias, &_fn##_);
149149
_GET(_initialize);
150-
_GET(_start);
151-
_GET(__wasm_call_ctors);
150+
if (_initialize_) {
151+
_GET(main);
152+
} else {
153+
_GET(_start);
154+
}
152155

153156
_GET(malloc);
154157
if (!malloc_) {
@@ -284,11 +287,19 @@ ContextBase *WasmBase::getRootContext(const std::shared_ptr<PluginBase> &plugin,
284287

285288
void WasmBase::startVm(ContextBase *root_context) {
286289
if (_initialize_) {
290+
// WASI reactor.
287291
_initialize_(root_context);
292+
if (main_) {
293+
// Call main() if it exists in WASI reactor, to allow module to
294+
// do early initialization (e.g. configure SDK).
295+
//
296+
// Re-using main() keeps this consistent when switching between
297+
// WASI command (that calls main()) and reactor (that doesn't).
298+
main_(root_context, Word(0), Word(0));
299+
}
288300
} else if (_start_) {
301+
// WASI command.
289302
_start_(root_context);
290-
} else if (__wasm_call_ctors_) {
291-
__wasm_call_ctors_(root_context);
292303
}
293304
}
294305

0 commit comments

Comments
 (0)