Skip to content

Commit

Permalink
Allow finer control of start function on instantiation
Browse files Browse the repository at this point in the history
Tries to address
bytecodealliance#4047.

Before this change, wasm_runtime_instantiate would execute the start
function unconditionally, correctly implementing the spec. However, if
there is an infinite loop in the start function, there was no way to
interrupt execution.

This change introduces a parameter to InstantiationArgs indicating
whether the start function should be immediately invoked. If not,
wasm_runtime_instantiate returns a module instance that is initialized
except for the start function.

This change adds a wasm_runtime_instantiate_run_start_func function
which performs this last instantiation step. The user may prepare a
timeout in advance of calling this to guard against expensive/infinite
loops.

This change also demonstrates a possible technique for doing this in
iwasm.c.
  • Loading branch information
sjamesr committed Feb 10, 2025
1 parent 7b724e2 commit cd6cd60
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 45 deletions.
27 changes: 19 additions & 8 deletions core/iwasm/common/wasm_runtime_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1622,13 +1622,24 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module,
WASMModuleInstanceCommon *parent,
WASMExecEnv *exec_env_main, uint32 stack_size,
uint32 heap_size, uint32 max_memory_pages,
char *error_buf, uint32 error_buf_size)
bool run_start_function, char *error_buf,
uint32 error_buf_size)
{
#if WASM_ENABLE_INTERP != 0
if (module->module_type == Wasm_Module_Bytecode)
return (WASMModuleInstanceCommon *)wasm_instantiate(
(WASMModule *)module, (WASMModuleInstance *)parent, exec_env_main,
stack_size, heap_size, max_memory_pages, error_buf, error_buf_size);
if (module->module_type == Wasm_Module_Bytecode) {
if (run_start_function) {
return (WASMModuleInstanceCommon *)wasm_instantiate(
(WASMModule *)module, (WASMModuleInstance *)parent,
exec_env_main, stack_size, heap_size, max_memory_pages,
error_buf, error_buf_size);
}

return (WASMModuleInstanceCommon *)
wasm_instantiate_without_start_function(
(WASMModule *)module, (WASMModuleInstance *)parent,
exec_env_main, stack_size, heap_size, max_memory_pages,
error_buf, error_buf_size);
}
#endif
#if WASM_ENABLE_AOT != 0
if (module->module_type == Wasm_Module_AoT)
Expand All @@ -1647,7 +1658,7 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size,
uint32 error_buf_size)
{
return wasm_runtime_instantiate_internal(module, NULL, NULL, stack_size,
heap_size, 0, error_buf,
heap_size, 0, true, error_buf,
error_buf_size);
}

Expand All @@ -1658,8 +1669,8 @@ wasm_runtime_instantiate_ex(WASMModuleCommon *module,
{
return wasm_runtime_instantiate_internal(
module, NULL, NULL, args->default_stack_size,
args->host_managed_heap_size, args->max_memory_pages, error_buf,
error_buf_size);
args->host_managed_heap_size, args->max_memory_pages,
args->run_start_function, error_buf, error_buf_size);
}

void
Expand Down
3 changes: 2 additions & 1 deletion core/iwasm/common/wasm_runtime_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,8 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module,
WASMModuleInstanceCommon *parent,
WASMExecEnv *exec_env_main, uint32 stack_size,
uint32 heap_size, uint32 max_memory_pages,
char *error_buf, uint32 error_buf_size);
bool run_start_function, char *error_buf,
uint32 error_buf_size);

/* Internal API */
void
Expand Down
13 changes: 13 additions & 0 deletions core/iwasm/include/wasm_export.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ typedef struct InstantiationArgs {
uint32_t default_stack_size;
uint32_t host_managed_heap_size;
uint32_t max_memory_pages;

bool run_start_function;
} InstantiationArgs;
#endif /* INSTANTIATION_ARGS_OPTION_DEFINED */

Expand Down Expand Up @@ -719,6 +721,17 @@ wasm_runtime_instantiate_ex(const wasm_module_t module,
const InstantiationArgs *args, char *error_buf,
uint32_t error_buf_size);

/**
* Run the start function of an otherwise instantiated module. See
* InstantiationArgs.run_start_function.
*/
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_instantiate_run_start_func(wasm_module_inst_t module,
wasm_module_inst_t parent,
wasm_exec_env_t exec_env,
char *error_buf,
uint32_t error_buf_size);

/**
* Set the running mode of a WASM module instance, override the
* default running mode of the runtime. Note that it only makes sense when
Expand Down
65 changes: 54 additions & 11 deletions core/iwasm/interpreter/wasm_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -2333,6 +2333,25 @@ wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode)
return set_running_mode(module_inst, running_mode, false);
}

bool
wasm_runtime_instantiate_run_start_func(wasm_module_inst_t module_inst,
wasm_module_inst_t parent,
wasm_exec_env_t exec_env,
char *error_buf,
uint32_t error_buf_size)
{
const bool is_sub_inst = parent != NULL;
if (!execute_post_instantiate_functions((WASMModuleInstance *)module_inst,
is_sub_inst, exec_env)) {
set_error_buf(error_buf, error_buf_size,
((WASMModuleInstance *)module_inst)->cur_exception);
wasm_runtime_deinstantiate(module_inst);
return false;
}

return true;
}

/**
* Instantiate module
*/
Expand All @@ -2341,6 +2360,41 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
WASMExecEnv *exec_env_main, uint32 stack_size,
uint32 heap_size, uint32 max_memory_pages, char *error_buf,
uint32 error_buf_size)
{
WASMModuleInstance *module_inst = wasm_instantiate_without_start_function(
module, parent, exec_env_main, stack_size, heap_size, max_memory_pages,
error_buf, error_buf_size);

if (!module_inst) {
// wasm_instantiate_without_start_function will deinstantiate on
// failure.
return NULL;
}

if (!wasm_runtime_instantiate_run_start_func(
(WASMModuleInstanceCommon *)module_inst,
(WASMModuleInstanceCommon *)parent, exec_env_main, error_buf,
error_buf_size)) {
// run_start_func will deinstantiate on failure.
set_error_buf(error_buf, error_buf_size, module_inst->cur_exception);
return NULL;
}

#if WASM_ENABLE_MEMORY_TRACING != 0
wasm_runtime_dump_module_inst_mem_consumption(
(WASMModuleInstanceCommon *)module_inst);
#endif

return module_inst;
}

WASMModuleInstance *
wasm_instantiate_without_start_function(WASMModule *module,
WASMModuleInstance *parent,
WASMExecEnv *exec_env_main,
uint32 stack_size, uint32 heap_size,
uint32 max_memory_pages,
char *error_buf, uint32 error_buf_size)
{
WASMModuleInstance *module_inst;
WASMGlobalInstance *globals = NULL, *global;
Expand Down Expand Up @@ -3257,17 +3311,6 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
&module_inst->e->functions[module->start_function];
}

if (!execute_post_instantiate_functions(module_inst, is_sub_inst,
exec_env_main)) {
set_error_buf(error_buf, error_buf_size, module_inst->cur_exception);
goto fail;
}

#if WASM_ENABLE_MEMORY_TRACING != 0
wasm_runtime_dump_module_inst_mem_consumption(
(WASMModuleInstanceCommon *)module_inst);
#endif

(void)global_data_end;
return module_inst;

Expand Down
8 changes: 8 additions & 0 deletions core/iwasm/interpreter/wasm_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,14 @@ bool
wasm_resolve_import_func(const WASMModule *module,
WASMFunctionImport *function);

WASMModuleInstance *
wasm_instantiate_without_start_function(WASMModule *module,
WASMModuleInstance *parent,
WASMExecEnv *exec_env_main,
uint32 stack_size, uint32 heap_size,
uint32 max_memory_pages,
char *error_buf, uint32 error_buf_size);

WASMModuleInstance *
wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
WASMExecEnv *exec_env_main, uint32 stack_size,
Expand Down
2 changes: 1 addition & 1 deletion core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
#endif

if (!(new_module_inst = wasm_runtime_instantiate_internal(
module, module_inst, exec_env, stack_size, 0, 0, NULL, 0)))
module, module_inst, exec_env, stack_size, 0, 0, true, NULL, 0)))
return -1;

/* Set custom_data to new module instance */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
stack_size = ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;

if (!(new_module_inst = wasm_runtime_instantiate_internal(
module, module_inst, exec_env, stack_size, 0, 0, NULL, 0)))
module, module_inst, exec_env, stack_size, 0, 0, true, NULL, 0)))
return -1;

wasm_runtime_set_custom_data_internal(
Expand Down
3 changes: 2 additions & 1 deletion core/iwasm/libraries/thread-mgr/thread_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,8 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
}

if (!(new_module_inst = wasm_runtime_instantiate_internal(
module, module_inst, exec_env, stack_size, 0, 0, NULL, 0))) {
module, module_inst, exec_env, stack_size, 0, 0, true, NULL,
0))) {
return NULL;
}

Expand Down
56 changes: 34 additions & 22 deletions product-mini/platforms/posix/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -945,10 +945,38 @@ main(int argc, char *argv[])
libc_wasi_init(wasm_module, argc, argv, &wasi_parse_ctx);
#endif

InstantiationArgs args = {
.default_stack_size = stack_size,
.host_managed_heap_size = heap_size,
.max_memory_pages = 0,
.run_start_function = false,
};

/* instantiate the module */
if (!(wasm_module_inst =
wasm_runtime_instantiate(wasm_module, stack_size, heap_size,
error_buf, sizeof(error_buf)))) {
if (!(wasm_module_inst = wasm_runtime_instantiate_ex(
wasm_module, &args, error_buf, sizeof(error_buf)))) {
printf("%s\n", error_buf);
goto fail3;
}

#if WASM_ENABLE_THREAD_MGR != 0
struct timeout_arg timeout_arg;
korp_tid timeout_tid;
if (timeout_ms >= 0) {
timeout_arg.timeout_ms = timeout_ms;
timeout_arg.inst = wasm_module_inst;
timeout_arg.cancel = false;
ret = os_thread_create(&timeout_tid, timeout_thread, &timeout_arg,
APP_THREAD_STACK_SIZE_DEFAULT);
if (ret != 0) {
printf("Failed to start timeout\n");
goto fail4;
}
}
#endif

if (!wasm_runtime_instantiate_run_start_func(
wasm_module_inst, NULL, NULL, error_buf, sizeof(error_buf))) {
printf("%s\n", error_buf);
goto fail3;
}
Expand All @@ -966,27 +994,11 @@ main(int argc, char *argv[])
uint32_t debug_port;
if (exec_env == NULL) {
printf("%s\n", wasm_runtime_get_exception(wasm_module_inst));
goto fail4;
goto fail5;
}
debug_port = wasm_runtime_start_debug_instance(exec_env);
if (debug_port == 0) {
printf("Failed to start debug instance\n");
goto fail4;
}
}
#endif

#if WASM_ENABLE_THREAD_MGR != 0
struct timeout_arg timeout_arg;
korp_tid timeout_tid;
if (timeout_ms >= 0) {
timeout_arg.timeout_ms = timeout_ms;
timeout_arg.inst = wasm_module_inst;
timeout_arg.cancel = false;
ret = os_thread_create(&timeout_tid, timeout_thread, &timeout_arg,
APP_THREAD_STACK_SIZE_DEFAULT);
if (ret != 0) {
printf("Failed to start timeout\n");
goto fail5;
}
}
Expand Down Expand Up @@ -1035,10 +1047,10 @@ main(int argc, char *argv[])
}
#endif

#if WASM_ENABLE_THREAD_MGR != 0
#if WASM_ENABLE_DEBUG_INTERP != 0
fail5:
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
#if WASM_ENABLE_THREAD_MGR != 0
fail4:
#endif
/* destroy the module instance */
Expand Down

0 comments on commit cd6cd60

Please sign in to comment.