From 3d416abaadc1de19510f2a51cd64c557c33ab4c6 Mon Sep 17 00:00:00 2001 From: Xu Jun <693788454@qq.com> Date: Sun, 15 Jan 2023 23:45:38 +0800 Subject: [PATCH 01/20] main thread spread exception --- core/iwasm/aot/aot_runtime.c | 3 ++- core/iwasm/common/wasm_application.c | 9 +++++++++ core/iwasm/common/wasm_runtime_common.c | 7 +++++++ core/iwasm/interpreter/wasm_interp_classic.c | 3 ++- core/iwasm/interpreter/wasm_runtime.c | 3 ++- 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 9d4d763b5b..cbd23aa7cd 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -902,7 +902,7 @@ create_exports(AOTModuleInstance *module_inst, AOTModule *module, static bool clear_wasi_proc_exit_exception(AOTModuleInstance *module_inst) { -#if WASM_ENABLE_LIBC_WASI != 0 +#if (WASM_ENABLE_LIBC_WASI != 0) && (WASM_ENABLE_THREAD_MGR == 0) const char *exception = aot_get_exception(module_inst); if (exception && !strcmp(exception, "Exception: wasi proc exit")) { /* The "wasi proc exit" exception is thrown by native lib to @@ -913,6 +913,7 @@ clear_wasi_proc_exit_exception(AOTModuleInstance *module_inst) } return false; #else + (void)module_inst; return false; #endif } diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index 8445652f64..99f13af253 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -209,6 +209,7 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, #if WASM_ENABLE_THREAD_MGR != 0 || WASM_ENABLE_MEMORY_PROFILING != 0 WASMExecEnv *exec_env; #endif + const char *exception = NULL; ret = execute_main(module_inst, argc, argv); @@ -230,6 +231,14 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, wasm_runtime_dump_perf_profiling(module_inst); #endif +#if (WASM_ENABLE_LIBC_WASI != 0) && (WASM_ENABLE_THREAD_MGR != 0) + exception = wasm_runtime_get_exception(module_inst); + if (exception && strcmp(exception, "Exception: wasi proc exit") == 0) + wasm_runtime_clear_exception(module_inst); +#else + (void)exception; +#endif + return (ret && !wasm_runtime_get_exception(module_inst)) ? true : false; } diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 88dd1c19d4..020d840495 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1786,6 +1786,10 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env, if (new_argv != argv) { wasm_runtime_free(new_argv); } +#if WASM_ENABLE_THREAD_MGR != 0 + if (wasm_runtime_get_exception(exec_env->module_inst)) + wasm_cluster_spread_exception(exec_env); +#endif return false; } @@ -1794,6 +1798,9 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env, result_argc, argv)) { wasm_runtime_set_exception(exec_env->module_inst, "the result conversion is failed"); +#if WASM_ENABLE_THREAD_MGR != 0 + wasm_cluster_spread_exception(exec_env); +#endif return false; } #endif diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 46c5ff444f..bf18e7238f 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -4021,7 +4021,7 @@ fast_jit_call_func_bytecode(WASMModuleInstance *module_inst, static bool clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) { -#if WASM_ENABLE_LIBC_WASI != 0 +#if (WASM_ENABLE_LIBC_WASI != 0) && (WASM_ENABLE_THREAD_MGR == 0) const char *exception = wasm_get_exception(module_inst); if (exception && !strcmp(exception, "Exception: wasi proc exit")) { /* The "wasi proc exit" exception is thrown by native lib to @@ -4032,6 +4032,7 @@ clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) } return false; #else + (void)module_inst; return false; #endif } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index cf363af4a1..3524dbabd7 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2036,7 +2036,7 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name) static bool clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) { -#if WASM_ENABLE_LIBC_WASI != 0 +#if (WASM_ENABLE_LIBC_WASI != 0) && (WASM_ENABLE_THREAD_MGR == 0) const char *exception = wasm_get_exception(module_inst); if (exception && !strcmp(exception, "Exception: wasi proc exit")) { /* The "wasi proc exit" exception is thrown by native lib to @@ -2047,6 +2047,7 @@ clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) } return false; #else + (void)module_inst; return false; #endif } From 9067254c09b82237d42cb919bed2d86855c933b1 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 09:57:35 +0800 Subject: [PATCH 02/20] terminate threads when spread exception --- .../libraries/thread-mgr/thread_manager.c | 21 ++++++++++---- samples/multi-thread/wasm-apps/CMakeLists.txt | 3 ++ .../wasm-apps/main_thread_exception.c | 29 +++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 samples/multi-thread/wasm-apps/main_thread_exception.c diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 4408b01331..4d86f9cc49 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -772,6 +772,17 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval) os_thread_exit(retval); } +static void +set_thread_cancel_flags(WASMExecEnv *exec_env) +{ + /* Set the termination flag */ +#if WASM_ENABLE_DEBUG_INTERP != 0 + wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM); +#else + exec_env->suspend_flags.flags |= 0x01; +#endif +} + int32 wasm_cluster_cancel_thread(WASMExecEnv *exec_env) { @@ -783,12 +794,8 @@ wasm_cluster_cancel_thread(WASMExecEnv *exec_env) } os_mutex_unlock(&cluster_list_lock); - /* Set the termination flag */ -#if WASM_ENABLE_DEBUG_INTERP != 0 - wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM); -#else - exec_env->suspend_flags.flags |= 0x01; -#endif + set_thread_cancel_flags(exec_env); + return 0; } @@ -927,6 +934,8 @@ set_exception_visitor(void *node, void *user_data) if (curr_exec_env != exec_env) { curr_module_inst = get_module_inst(curr_exec_env); wasm_runtime_set_exception(curr_module_inst, exception); + /* Terminate the thread so it can exit from dead loops */ + set_thread_cancel_flags(curr_exec_env); } } diff --git a/samples/multi-thread/wasm-apps/CMakeLists.txt b/samples/multi-thread/wasm-apps/CMakeLists.txt index 44ced1cc83..ec8f7eefbb 100644 --- a/samples/multi-thread/wasm-apps/CMakeLists.txt +++ b/samples/multi-thread/wasm-apps/CMakeLists.txt @@ -38,3 +38,6 @@ set (CMAKE_EXE_LINKER_FLAGS add_executable(test.wasm main.c) target_link_libraries(test.wasm) + +add_executable(main_thread_exception.wasm main_thread_exception.c) +target_link_libraries(main_thread_exception.wasm) diff --git a/samples/multi-thread/wasm-apps/main_thread_exception.c b/samples/multi-thread/wasm-apps/main_thread_exception.c new file mode 100644 index 0000000000..74bfd9fd37 --- /dev/null +++ b/samples/multi-thread/wasm-apps/main_thread_exception.c @@ -0,0 +1,29 @@ +#include +#include + +typedef struct ThreadArgs { + int start; + int length; +} ThreadArgs; + +void *thread(void *args) +{ + while (1) { + /* When other thread (including main thread) throw exception, + this thread can successfully exit the dead loop */ + } +} + +int main() +{ + pthread_t tids; + + if (pthread_create(&tids, NULL, thread, NULL) != 0) { + printf("pthread_create failed\n"); + } + + /* Trigger an exception */ + *(int *)(-1) = 100; + + return 0; +} From c72dfc9d88754971471827c4e78e852461bc0bbc Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 10:02:12 +0800 Subject: [PATCH 03/20] add file header --- samples/multi-thread/wasm-apps/main_thread_exception.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/samples/multi-thread/wasm-apps/main_thread_exception.c b/samples/multi-thread/wasm-apps/main_thread_exception.c index 74bfd9fd37..615aa909f0 100644 --- a/samples/multi-thread/wasm-apps/main_thread_exception.c +++ b/samples/multi-thread/wasm-apps/main_thread_exception.c @@ -1,3 +1,8 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + #include #include From 41742150ba22ddc11fe9f79f2798541477e5b82a Mon Sep 17 00:00:00 2001 From: Xu Jun <693788454@qq.com> Date: Mon, 16 Jan 2023 10:01:49 +0800 Subject: [PATCH 04/20] auto format --- samples/multi-thread/wasm-apps/main_thread_exception.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/samples/multi-thread/wasm-apps/main_thread_exception.c b/samples/multi-thread/wasm-apps/main_thread_exception.c index 615aa909f0..f0feafd48a 100644 --- a/samples/multi-thread/wasm-apps/main_thread_exception.c +++ b/samples/multi-thread/wasm-apps/main_thread_exception.c @@ -11,7 +11,8 @@ typedef struct ThreadArgs { int length; } ThreadArgs; -void *thread(void *args) +void * +thread(void *args) { while (1) { /* When other thread (including main thread) throw exception, @@ -19,7 +20,8 @@ void *thread(void *args) } } -int main() +int +main() { pthread_t tids; From 2d3da36da1639bfd8c39d0eeef615c7e599e772d Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 13:59:56 +0800 Subject: [PATCH 05/20] spread exception during throwing --- core/iwasm/aot/aot_runtime.c | 5 ----- core/iwasm/common/wasm_runtime_common.c | 14 ++++++-------- core/iwasm/interpreter/wasm_interp_classic.c | 5 ----- core/iwasm/interpreter/wasm_runtime.c | 5 ----- .../libraries/lib-pthread/lib_pthread_wrapper.c | 3 +-- core/iwasm/libraries/thread-mgr/thread_manager.c | 14 +++++++++++--- 6 files changed, 18 insertions(+), 28 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index cbd23aa7cd..220d45a4c0 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -902,7 +902,6 @@ create_exports(AOTModuleInstance *module_inst, AOTModule *module, static bool clear_wasi_proc_exit_exception(AOTModuleInstance *module_inst) { -#if (WASM_ENABLE_LIBC_WASI != 0) && (WASM_ENABLE_THREAD_MGR == 0) const char *exception = aot_get_exception(module_inst); if (exception && !strcmp(exception, "Exception: wasi proc exit")) { /* The "wasi proc exit" exception is thrown by native lib to @@ -912,10 +911,6 @@ clear_wasi_proc_exit_exception(AOTModuleInstance *module_inst) return true; } return false; -#else - (void)module_inst; - return false; -#endif } static bool diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 020d840495..8600bc3627 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1786,10 +1786,6 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env, if (new_argv != argv) { wasm_runtime_free(new_argv); } -#if WASM_ENABLE_THREAD_MGR != 0 - if (wasm_runtime_get_exception(exec_env->module_inst)) - wasm_cluster_spread_exception(exec_env); -#endif return false; } @@ -1798,9 +1794,6 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env, result_argc, argv)) { wasm_runtime_set_exception(exec_env->module_inst, "the result conversion is failed"); -#if WASM_ENABLE_THREAD_MGR != 0 - wasm_cluster_spread_exception(exec_env); -#endif return false; } #endif @@ -2157,9 +2150,14 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm) void wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) { - if (exception) + if (exception) { snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), "Exception: %s", exception); +#if WASM_ENABLE_THREAD_MGR != 0 + wasm_cluster_spread_exception( + wasm_clusters_search_exec_env(module_inst)); +#endif + } else module_inst->cur_exception[0] = '\0'; } diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index bf18e7238f..5ce1f6bdd7 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -4021,7 +4021,6 @@ fast_jit_call_func_bytecode(WASMModuleInstance *module_inst, static bool clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) { -#if (WASM_ENABLE_LIBC_WASI != 0) && (WASM_ENABLE_THREAD_MGR == 0) const char *exception = wasm_get_exception(module_inst); if (exception && !strcmp(exception, "Exception: wasi proc exit")) { /* The "wasi proc exit" exception is thrown by native lib to @@ -4031,10 +4030,6 @@ clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) return true; } return false; -#else - (void)module_inst; - return false; -#endif } static bool diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 3524dbabd7..c99e755e59 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2036,7 +2036,6 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name) static bool clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) { -#if (WASM_ENABLE_LIBC_WASI != 0) && (WASM_ENABLE_THREAD_MGR == 0) const char *exception = wasm_get_exception(module_inst); if (exception && !strcmp(exception, "Exception: wasi proc exit")) { /* The "wasi proc exit" exception is thrown by native lib to @@ -2046,10 +2045,6 @@ clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) return true; } return false; -#else - (void)module_inst; - return false; -#endif } #ifdef OS_ENABLE_HW_BOUND_CHECK diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index 2fb7033f36..3bf3269b80 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -520,8 +520,7 @@ pthread_start_routine(void *arg) if (!wasm_runtime_call_indirect(exec_env, routine_args->elem_index, 1, argv)) { - if (wasm_runtime_get_exception(module_inst)) - wasm_cluster_spread_exception(exec_env); + /* Exception has already been spread during throwing */ } /* destroy pthread key values */ diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 4d86f9cc49..1c57b25224 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -926,14 +926,22 @@ set_exception_visitor(void *node, void *user_data) WASMExecEnv *curr_exec_env = (WASMExecEnv *)node; WASMExecEnv *exec_env = (WASMExecEnv *)user_data; WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env); - WASMModuleInstanceCommon *curr_module_inst = get_module_inst(curr_exec_env); + WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst; const char *exception = wasm_runtime_get_exception(module_inst); /* skip "Exception: " */ exception += 11; if (curr_exec_env != exec_env) { - curr_module_inst = get_module_inst(curr_exec_env); - wasm_runtime_set_exception(curr_module_inst, exception); + WASMModuleInstance *curr_wasm_inst; + WASMModuleInstanceCommon *curr_module_inst = + get_module_inst(curr_exec_env); + bh_assert(curr_module_inst); + + curr_wasm_inst = (WASMModuleInstance *)curr_module_inst; + + bh_memcpy_s(curr_wasm_inst->cur_exception, + sizeof(curr_wasm_inst->cur_exception), + wasm_inst->cur_exception, sizeof(wasm_inst->cur_exception)); /* Terminate the thread so it can exit from dead loops */ set_thread_cancel_flags(curr_exec_env); } From ff1bd10d9768253f89a3b02af16b7204c195b111 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 14:04:04 +0800 Subject: [PATCH 06/20] restore unused modification --- core/iwasm/aot/aot_runtime.c | 3 +++ core/iwasm/common/wasm_application.c | 9 --------- core/iwasm/interpreter/wasm_runtime.c | 3 +++ 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 220d45a4c0..7104cbeeb5 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -902,6 +902,7 @@ create_exports(AOTModuleInstance *module_inst, AOTModule *module, static bool clear_wasi_proc_exit_exception(AOTModuleInstance *module_inst) { +#if WASM_ENABLE_LIBC_WASI != 0 const char *exception = aot_get_exception(module_inst); if (exception && !strcmp(exception, "Exception: wasi proc exit")) { /* The "wasi proc exit" exception is thrown by native lib to @@ -910,7 +911,9 @@ clear_wasi_proc_exit_exception(AOTModuleInstance *module_inst) aot_set_exception(module_inst, NULL); return true; } +#else return false; +#endif } static bool diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index 99f13af253..8445652f64 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -209,7 +209,6 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, #if WASM_ENABLE_THREAD_MGR != 0 || WASM_ENABLE_MEMORY_PROFILING != 0 WASMExecEnv *exec_env; #endif - const char *exception = NULL; ret = execute_main(module_inst, argc, argv); @@ -231,14 +230,6 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, wasm_runtime_dump_perf_profiling(module_inst); #endif -#if (WASM_ENABLE_LIBC_WASI != 0) && (WASM_ENABLE_THREAD_MGR != 0) - exception = wasm_runtime_get_exception(module_inst); - if (exception && strcmp(exception, "Exception: wasi proc exit") == 0) - wasm_runtime_clear_exception(module_inst); -#else - (void)exception; -#endif - return (ret && !wasm_runtime_get_exception(module_inst)) ? true : false; } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index c99e755e59..fce14916fb 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2036,6 +2036,7 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name) static bool clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) { +#if WASM_ENABLE_LIBC_WASI != 0 const char *exception = wasm_get_exception(module_inst); if (exception && !strcmp(exception, "Exception: wasi proc exit")) { /* The "wasi proc exit" exception is thrown by native lib to @@ -2044,7 +2045,9 @@ clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) wasm_set_exception(module_inst, NULL); return true; } +#else return false; +#endif } #ifdef OS_ENABLE_HW_BOUND_CHECK From a4a2bb67640a68bb0a5df5eb4a5ca1f55e9c5dc1 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 14:05:37 +0800 Subject: [PATCH 07/20] minor fix --- core/iwasm/aot/aot_runtime.c | 1 + core/iwasm/interpreter/wasm_interp_classic.c | 4 ++++ core/iwasm/interpreter/wasm_runtime.c | 1 + 3 files changed, 6 insertions(+) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 7104cbeeb5..9d4d763b5b 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -911,6 +911,7 @@ clear_wasi_proc_exit_exception(AOTModuleInstance *module_inst) aot_set_exception(module_inst, NULL); return true; } + return false; #else return false; #endif diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 5ce1f6bdd7..46c5ff444f 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -4021,6 +4021,7 @@ fast_jit_call_func_bytecode(WASMModuleInstance *module_inst, static bool clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) { +#if WASM_ENABLE_LIBC_WASI != 0 const char *exception = wasm_get_exception(module_inst); if (exception && !strcmp(exception, "Exception: wasi proc exit")) { /* The "wasi proc exit" exception is thrown by native lib to @@ -4030,6 +4031,9 @@ clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) return true; } return false; +#else + return false; +#endif } static bool diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index fce14916fb..cf363af4a1 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2045,6 +2045,7 @@ clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) wasm_set_exception(module_inst, NULL); return true; } + return false; #else return false; #endif From 0016228dd83c739a36aa57fe767fa7a858ed8e89 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 15:42:15 +0800 Subject: [PATCH 08/20] refactor wasi proc exception processing --- core/iwasm/aot/aot_runtime.c | 39 +++------------ core/iwasm/common/wasm_runtime_common.c | 52 +++++++++++++++++--- core/iwasm/interpreter/wasm_interp_classic.c | 29 ----------- core/iwasm/interpreter/wasm_runtime.c | 22 +-------- 4 files changed, 51 insertions(+), 91 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 9d4d763b5b..ceb71f8f90 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -899,24 +899,6 @@ create_exports(AOTModuleInstance *module_inst, AOTModule *module, return create_export_funcs(module_inst, module, error_buf, error_buf_size); } -static bool -clear_wasi_proc_exit_exception(AOTModuleInstance *module_inst) -{ -#if WASM_ENABLE_LIBC_WASI != 0 - const char *exception = aot_get_exception(module_inst); - if (exception && !strcmp(exception, "Exception: wasi proc exit")) { - /* The "wasi proc exit" exception is thrown by native lib to - let wasm app exit, which is a normal behavior, we clear - the exception here. */ - aot_set_exception(module_inst, NULL); - return true; - } - return false; -#else - return false; -#endif -} - static bool execute_post_inst_function(AOTModuleInstance *module_inst) { @@ -931,6 +913,9 @@ execute_post_inst_function(AOTModuleInstance *module_inst) NULL); } +extern bool +clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm); + static bool execute_start_function(AOTModuleInstance *module_inst) { @@ -956,7 +941,8 @@ execute_start_function(AOTModuleInstance *module_inst) u.f(exec_env); wasm_exec_env_destroy(exec_env); - (void)clear_wasi_proc_exit_exception(module_inst); + (void)clear_wasi_proc_exit_exception( + (WASMModuleInstanceCommon *)module_inst); return !aot_get_exception(module_inst); } @@ -1407,13 +1393,6 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, ret = invoke_native_internal(exec_env, function->u.func.func_ptr, func_type, NULL, NULL, argv1, argc, argv); - if (!ret || aot_get_exception(module_inst)) { - if (clear_wasi_proc_exit_exception(module_inst)) - ret = true; - else - ret = false; - } - #if WASM_ENABLE_DUMP_CALL_STACK != 0 if (!ret) { if (aot_create_call_stack(exec_env)) { @@ -1473,9 +1452,6 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, ret = invoke_native_internal(exec_env, function->u.func.func_ptr, func_type, NULL, NULL, argv, argc, argv); - if (clear_wasi_proc_exit_exception(module_inst)) - ret = true; - #if WASM_ENABLE_DUMP_CALL_STACK != 0 if (aot_get_exception(module_inst)) { if (aot_create_call_stack(exec_env)) { @@ -1516,7 +1492,7 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst, } } - ret = aot_call_function(exec_env, func, argc, argv); + ret = wasm_runtime_call_wasm(exec_env, func, argc, argv); /* don't destroy the exec_env if it isn't created in this function */ if (!existing_exec_env) @@ -2006,9 +1982,6 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, } fail: - if (clear_wasi_proc_exit_exception(module_inst)) - return true; - #ifdef OS_ENABLE_HW_BOUND_CHECK wasm_runtime_access_exce_check_guard_page(); #endif diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 8600bc3627..9d85f4c6d5 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -9,6 +9,7 @@ #include "bh_log.h" #include "wasm_runtime_common.h" #include "wasm_memory.h" +#include #if WASM_ENABLE_INTERP != 0 #include "../interpreter/wasm_runtime.h" #endif @@ -1743,6 +1744,29 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env, } #endif +bool +clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm) +{ +#if WASM_ENABLE_LIBC_WASI != 0 + WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; + + bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode + || module_inst_comm->module_type == Wasm_Module_AoT); + + const char *exception = wasm_get_exception(module_inst); + if (exception && !strcmp(exception, "Exception: wasi proc exit")) { + /* The "wasi proc exit" exception is thrown by native lib to + let wasm app exit, which is a normal behavior, we clear + the exception here. */ + aot_set_exception(module_inst, NULL); + return true; + } + return false; +#else + return false; +#endif +} + bool wasm_runtime_call_wasm(WASMExecEnv *exec_env, WASMFunctionInstanceCommon *function, uint32 argc, @@ -1783,10 +1807,15 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env, param_argc, new_argv); #endif if (!ret) { - if (new_argv != argv) { - wasm_runtime_free(new_argv); + if (clear_wasi_proc_exit_exception(exec_env->module_inst)) { + ret = true; + } + else { + if (new_argv != argv) { + wasm_runtime_free(new_argv); + } + return false; } - return false; } #if WASM_ENABLE_REF_TYPES != 0 @@ -2154,8 +2183,8 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), "Exception: %s", exception); #if WASM_ENABLE_THREAD_MGR != 0 - wasm_cluster_spread_exception( - wasm_clusters_search_exec_env(module_inst)); + wasm_cluster_spread_exception(wasm_clusters_search_exec_env( + (WASMModuleInstanceCommon *)module_inst)); #endif } else @@ -4184,6 +4213,8 @@ bool wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices, uint32 argc, uint32 argv[]) { + bool ret = false; + if (!wasm_runtime_exec_env_check(exec_env)) { LOG_ERROR("Invalid exec env stack info."); return false; @@ -4195,13 +4226,18 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices, #if WASM_ENABLE_INTERP != 0 if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) - return wasm_call_indirect(exec_env, 0, element_indices, argc, argv); + ret = wasm_call_indirect(exec_env, 0, element_indices, argc, argv); #endif #if WASM_ENABLE_AOT != 0 if (exec_env->module_inst->module_type == Wasm_Module_AoT) - return aot_call_indirect(exec_env, 0, element_indices, argc, argv); + ret = aot_call_indirect(exec_env, 0, element_indices, argc, argv); #endif - return false; + + if (!ret && clear_wasi_proc_exit_exception(exec_env->module_inst)) { + ret = true; + } + + return ret; } static void diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 46c5ff444f..e49b885ce7 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -4018,24 +4018,6 @@ fast_jit_call_func_bytecode(WASMModuleInstance *module_inst, #endif /* end of WASM_ENABLE_FAST_JIT != 0 */ #if WASM_ENABLE_JIT != 0 -static bool -clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) -{ -#if WASM_ENABLE_LIBC_WASI != 0 - const char *exception = wasm_get_exception(module_inst); - if (exception && !strcmp(exception, "Exception: wasi proc exit")) { - /* The "wasi proc exit" exception is thrown by native lib to - let wasm app exit, which is a normal behavior, we clear - the exception here. */ - wasm_set_exception(module_inst, NULL); - return true; - } - return false; -#else - return false; -#endif -} - static bool llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, @@ -4095,14 +4077,6 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, ret = wasm_runtime_invoke_native( exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL, argv1, argc, argv); - - if (!ret || wasm_get_exception(module_inst)) { - if (clear_wasi_proc_exit_exception(module_inst)) - ret = true; - else - ret = false; - } - if (!ret) { if (argv1 != argv1_buf) wasm_runtime_free(argv1); @@ -4147,9 +4121,6 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL, argv, argc, argv); - if (clear_wasi_proc_exit_exception(module_inst)) - ret = true; - return ret && !wasm_get_exception(module_inst) ? true : false; } } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index cf363af4a1..27b3c985b7 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2033,24 +2033,6 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name) } #endif -static bool -clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) -{ -#if WASM_ENABLE_LIBC_WASI != 0 - const char *exception = wasm_get_exception(module_inst); - if (exception && !strcmp(exception, "Exception: wasi proc exit")) { - /* The "wasi proc exit" exception is thrown by native lib to - let wasm app exit, which is a normal behavior, we clear - the exception here. */ - wasm_set_exception(module_inst, NULL); - return true; - } - return false; -#else - return false; -#endif -} - #ifdef OS_ENABLE_HW_BOUND_CHECK static void @@ -2160,7 +2142,6 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, wasm_exec_env_set_thread_info(exec_env); interp_call_wasm(module_inst, exec_env, function, argc, argv); - (void)clear_wasi_proc_exit_exception(module_inst); return !wasm_get_exception(module_inst) ? true : false; } @@ -2188,7 +2169,7 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst, } } - ret = wasm_call_function(exec_env, func, argc, argv); + ret = wasm_runtime_call_wasm(exec_env, func, argc, argv); /* don't destroy the exec_env if it isn't created in this function */ if (!existing_exec_env) @@ -2458,7 +2439,6 @@ call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, interp_call_wasm(module_inst, exec_env, func_inst, argc, argv); - (void)clear_wasi_proc_exit_exception(module_inst); return !wasm_get_exception(module_inst) ? true : false; got_exception: From 2426fd868146c18f0ddf678b71f6c2bc17cda050 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 15:59:55 +0800 Subject: [PATCH 09/20] minor fix --- core/iwasm/common/wasm_runtime_common.c | 1 - 1 file changed, 1 deletion(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 9d85f4c6d5..665fd0d239 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -9,7 +9,6 @@ #include "bh_log.h" #include "wasm_runtime_common.h" #include "wasm_memory.h" -#include #if WASM_ENABLE_INTERP != 0 #include "../interpreter/wasm_runtime.h" #endif From fc5c945aed2ba92831a0eb6ab9b288d5e1bb5ae6 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 16:08:47 +0800 Subject: [PATCH 10/20] fix build error --- core/iwasm/common/wasm_runtime_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 665fd0d239..012aea5cb0 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1757,7 +1757,7 @@ clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm) /* The "wasi proc exit" exception is thrown by native lib to let wasm app exit, which is a normal behavior, we clear the exception here. */ - aot_set_exception(module_inst, NULL); + wasm_set_exception(module_inst, NULL); return true; } return false; From c770575de5a3c3c174b104f698df296384914d85 Mon Sep 17 00:00:00 2001 From: Xu Jun <693788454@qq.com> Date: Mon, 16 Jan 2023 17:39:32 +0800 Subject: [PATCH 11/20] fix typo Co-authored-by: Marcin Kolny --- samples/multi-thread/wasm-apps/main_thread_exception.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/multi-thread/wasm-apps/main_thread_exception.c b/samples/multi-thread/wasm-apps/main_thread_exception.c index f0feafd48a..22da82464f 100644 --- a/samples/multi-thread/wasm-apps/main_thread_exception.c +++ b/samples/multi-thread/wasm-apps/main_thread_exception.c @@ -15,7 +15,7 @@ void * thread(void *args) { while (1) { - /* When other thread (including main thread) throw exception, + /* When other threads (including main thread) throw exception, this thread can successfully exit the dead loop */ } } From 12cf0aff55e466a5a1959d39142ce7146002a531 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 17:46:57 +0800 Subject: [PATCH 12/20] address some PR comments --- core/iwasm/libraries/thread-mgr/thread_manager.c | 8 ++------ samples/multi-thread/wasm-apps/main_thread_exception.c | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 1c57b25224..f416a2fe70 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -932,12 +932,8 @@ set_exception_visitor(void *node, void *user_data) exception += 11; if (curr_exec_env != exec_env) { - WASMModuleInstance *curr_wasm_inst; - WASMModuleInstanceCommon *curr_module_inst = - get_module_inst(curr_exec_env); - bh_assert(curr_module_inst); - - curr_wasm_inst = (WASMModuleInstance *)curr_module_inst; + WASMModuleInstance *curr_wasm_inst = + (WASMModuleInstance *)get_module_inst(curr_exec_env); bh_memcpy_s(curr_wasm_inst->cur_exception, sizeof(curr_wasm_inst->cur_exception), diff --git a/samples/multi-thread/wasm-apps/main_thread_exception.c b/samples/multi-thread/wasm-apps/main_thread_exception.c index 22da82464f..80f170d40d 100644 --- a/samples/multi-thread/wasm-apps/main_thread_exception.c +++ b/samples/multi-thread/wasm-apps/main_thread_exception.c @@ -30,7 +30,7 @@ main() } /* Trigger an exception */ - *(int *)(-1) = 100; + __builtin_trap(); return 0; } From 8f0a0467e771d9b1ec21ddb34b38d9a01ebd843e Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 19:25:57 +0800 Subject: [PATCH 13/20] add lock when traversing list in thread-mgr --- .../libraries/thread-mgr/thread_manager.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index f416a2fe70..98acce38b1 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -815,15 +815,19 @@ terminate_thread_visitor(void *node, void *user_data) void wasm_cluster_terminate_all(WASMCluster *cluster) { + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, terminate_thread_visitor, NULL); + os_mutex_unlock(&cluster->lock); } void wasm_cluster_terminate_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env) { + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, terminate_thread_visitor, (void *)exec_env); + os_mutex_unlock(&cluster->lock); } static void @@ -841,15 +845,19 @@ wait_for_thread_visitor(void *node, void *user_data) void wams_cluster_wait_for_all(WASMCluster *cluster) { + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, wait_for_thread_visitor, NULL); + os_mutex_unlock(&cluster->lock); } void wasm_cluster_wait_for_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env) { + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, wait_for_thread_visitor, (void *)exec_env); + os_mutex_unlock(&cluster->lock); } bool @@ -888,15 +896,19 @@ suspend_thread_visitor(void *node, void *user_data) void wasm_cluster_suspend_all(WASMCluster *cluster) { + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, suspend_thread_visitor, NULL); + os_mutex_unlock(&cluster->lock); } void wasm_cluster_suspend_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env) { + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, suspend_thread_visitor, (void *)exec_env); + os_mutex_unlock(&cluster->lock); } void @@ -917,7 +929,9 @@ resume_thread_visitor(void *node, void *user_data) void wasm_cluster_resume_all(WASMCluster *cluster) { + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, resume_thread_visitor, NULL); + os_mutex_unlock(&cluster->lock); } static void @@ -949,7 +963,9 @@ wasm_cluster_spread_exception(WASMExecEnv *exec_env) WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); bh_assert(cluster); + os_mutex_lock(&clsuter->lock); traverse_list(&cluster->exec_env_list, set_exception_visitor, exec_env); + os_mutex_unlock(&clsuter->lock); } static void @@ -977,7 +993,9 @@ wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst, cluster = wasm_exec_env_get_cluster(exec_env); bh_assert(cluster); + os_mutex_lock(&cluster->lock); traverse_list(&cluster->exec_env_list, set_custom_data_visitor, custom_data); + os_mutex_unlock(&cluster->lock); } } From 1ace00fafc6b7be4dcb9815350d6943be15a6254 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 19:59:01 +0800 Subject: [PATCH 14/20] avoid creating new thread while spreading exception --- core/iwasm/common/wasm_runtime_common.c | 13 ++-- .../libraries/thread-mgr/thread_manager.c | 77 ++++++++++++------- .../libraries/thread-mgr/thread_manager.h | 6 +- 3 files changed, 58 insertions(+), 38 deletions(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 012aea5cb0..2b5fdebbf9 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2181,13 +2181,16 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) if (exception) { snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), "Exception: %s", exception); -#if WASM_ENABLE_THREAD_MGR != 0 - wasm_cluster_spread_exception(wasm_clusters_search_exec_env( - (WASMModuleInstanceCommon *)module_inst)); -#endif } - else + else { module_inst->cur_exception[0] = '\0'; + } + +#if WASM_ENABLE_THREAD_MGR != 0 + wasm_cluster_spread_exception( + wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst), + exception ? false : true); +#endif } /* clang-format off */ diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 98acce38b1..8fb2264290 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -76,6 +76,7 @@ traverse_list(bh_list *l, list_visitor visitor, void *user_data) } } +/* The caller must lock cluster->lock */ static bool allocate_aux_stack(WASMCluster *cluster, uint32 *start, uint32 *size) { @@ -86,7 +87,6 @@ allocate_aux_stack(WASMCluster *cluster, uint32 *start, uint32 *size) if (!cluster->stack_segment_occupied) return false; - os_mutex_lock(&cluster->lock); for (i = 0; i < cluster_max_thread_num; i++) { if (!cluster->stack_segment_occupied[i]) { if (start) @@ -94,14 +94,14 @@ allocate_aux_stack(WASMCluster *cluster, uint32 *start, uint32 *size) if (size) *size = cluster->stack_size; cluster->stack_segment_occupied[i] = true; - os_mutex_unlock(&cluster->lock); return true; } } - os_mutex_unlock(&cluster->lock); + return false; } +/* The caller must lock cluster->lock */ static bool free_aux_stack(WASMCluster *cluster, uint32 start) { @@ -109,9 +109,7 @@ free_aux_stack(WASMCluster *cluster, uint32 start) for (i = 0; i < cluster_max_thread_num; i++) { if (start == cluster->stack_tops[i]) { - os_mutex_lock(&cluster->lock); cluster->stack_segment_occupied[i] = false; - os_mutex_unlock(&cluster->lock); return true; } } @@ -265,20 +263,21 @@ wasm_exec_env_get_cluster(WASMExecEnv *exec_env) return exec_env->cluster; } -bool +/* The caller must lock cluster->lock */ +static bool wasm_cluster_add_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env) { bool ret = true; exec_env->cluster = cluster; - os_mutex_lock(&cluster->lock); if (bh_list_insert(&cluster->exec_env_list, exec_env) != 0) ret = false; - os_mutex_unlock(&cluster->lock); + return ret; } +/* The caller must lock cluster->lock */ bool wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env) { @@ -301,10 +300,8 @@ wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env) } #endif - os_mutex_lock(&cluster->lock); if (bh_list_remove(&cluster->exec_env_list, exec_env) != 0) ret = false; - os_mutex_unlock(&cluster->lock); if (cluster->exec_env_list.len == 0) { /* exec_env_list empty, destroy the cluster */ @@ -374,6 +371,12 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) return NULL; } + os_mutex_lock(&cluster->lock); + + if (cluster->has_exception) { + goto fail1; + } + #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { stack_size = @@ -390,7 +393,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) if (!(new_module_inst = wasm_runtime_instantiate_internal( module, true, stack_size, 0, NULL, 0))) { - return NULL; + goto fail1; } /* Set custom_data to new module instance */ @@ -405,32 +408,36 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) new_exec_env = wasm_exec_env_create_internal(new_module_inst, exec_env->wasm_stack_size); if (!new_exec_env) - goto fail1; + goto fail2; if (!allocate_aux_stack(cluster, &aux_stack_start, &aux_stack_size)) { LOG_ERROR("thread manager error: " "failed to allocate aux stack space for new thread"); - goto fail2; + goto fail3; } /* Set aux stack for current thread */ if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start, aux_stack_size)) { - goto fail3; + goto fail4; } if (!wasm_cluster_add_exec_env(cluster, new_exec_env)) - goto fail3; + goto fail4; + + os_mutex_unlock(&cluster->lock); return new_exec_env; -fail3: +fail4: /* free the allocated aux stack space */ free_aux_stack(cluster, aux_stack_start); -fail2: +fail3: wasm_exec_env_destroy(new_exec_env); -fail1: +fail2: wasm_runtime_deinstantiate_internal(new_module_inst, true); +fail1: + os_mutex_unlock(&cluster->lock); return NULL; } @@ -496,25 +503,31 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, cluster = wasm_exec_env_get_cluster(exec_env); bh_assert(cluster); + os_mutex_lock(&cluster->lock); + + if (cluster->has_exception) { + goto fail1; + } + new_exec_env = wasm_exec_env_create_internal(module_inst, exec_env->wasm_stack_size); if (!new_exec_env) - return -1; + goto fail1; if (!allocate_aux_stack(cluster, &aux_stack_start, &aux_stack_size)) { LOG_ERROR("thread manager error: " "failed to allocate aux stack space for new thread"); - goto fail1; + goto fail2; } /* Set aux stack for current thread */ if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start, aux_stack_size)) { - goto fail2; + goto fail3; } if (!wasm_cluster_add_exec_env(cluster, new_exec_env)) - goto fail2; + goto fail3; new_exec_env->thread_start_routine = thread_routine; new_exec_env->thread_arg = arg; @@ -523,18 +536,23 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, != os_thread_create(&tid, thread_manager_start_routine, (void *)new_exec_env, APP_THREAD_STACK_SIZE_DEFAULT)) { - goto fail3; + goto fail4; } + os_mutex_unlock(&cluster->lock); + return 0; -fail3: +fail4: wasm_cluster_del_exec_env(cluster, new_exec_env); -fail2: +fail3: /* free the allocated aux stack space */ free_aux_stack(cluster, aux_stack_start); -fail1: +fail2: wasm_exec_env_destroy(new_exec_env); +fail1: + os_mutex_unlock(&cluster->lock); + return -1; } @@ -958,14 +976,15 @@ set_exception_visitor(void *node, void *user_data) } void -wasm_cluster_spread_exception(WASMExecEnv *exec_env) +wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear) { WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); bh_assert(cluster); - os_mutex_lock(&clsuter->lock); + os_mutex_lock(&cluster->lock); + cluster->has_exception = !clear; traverse_list(&cluster->exec_env_list, set_exception_visitor, exec_env); - os_mutex_unlock(&clsuter->lock); + os_mutex_unlock(&cluster->lock); } static void diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index c84d3c0219..bb245b5a2b 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -34,6 +34,7 @@ struct WASMCluster { uint32 stack_size; /* Record which segments are occupied */ bool *stack_segment_occupied; + bool has_exception; #if WASM_ENABLE_DEBUG_INTERP != 0 WASMDebugInstance *debug_inst; #endif @@ -113,9 +114,6 @@ void wasm_cluster_wait_for_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env); -bool -wasm_cluster_add_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env); - bool wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env); @@ -123,7 +121,7 @@ WASMExecEnv * wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst); void -wasm_cluster_spread_exception(WASMExecEnv *exec_env); +wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear); WASMExecEnv * wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env); From d0f5d94697d64d54967aca1465b827831b93592a Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 20:53:26 +0800 Subject: [PATCH 15/20] fix dead lock issue --- core/iwasm/common/wasm_exec_env.c | 2 + core/iwasm/common/wasm_runtime_common.c | 3 +- .../libraries/thread-mgr/thread_manager.c | 62 ++++++++++++++++--- .../libraries/thread-mgr/thread_manager.h | 7 +++ 4 files changed, 64 insertions(+), 10 deletions(-) diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c index 515a60b8e9..ab462d56d6 100644 --- a/core/iwasm/common/wasm_exec_env.c +++ b/core/iwasm/common/wasm_exec_env.c @@ -181,7 +181,9 @@ wasm_exec_env_destroy(WASMExecEnv *exec_env) the stopped thread will be overrided by other threads */ wasm_cluster_thread_exited(exec_env); #endif + os_mutex_lock(&cluster->lock); wasm_cluster_del_exec_env(cluster, exec_env); + os_mutex_unlock(&cluster->lock); } #endif /* end of WASM_ENABLE_THREAD_MGR */ diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 2b5fdebbf9..393826fbc2 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1747,12 +1747,13 @@ bool clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm) { #if WASM_ENABLE_LIBC_WASI != 0 + const char *exception; WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); - const char *exception = wasm_get_exception(module_inst); + exception = wasm_get_exception(module_inst); if (exception && !strcmp(exception, "Exception: wasi proc exit")) { /* The "wasi proc exit" exception is thrown by native lib to let wasm app exit, which is a normal behavior, we clear diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 8fb2264290..0e1189c464 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -450,8 +450,10 @@ wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env) bh_assert(cluster != NULL); /* Free aux stack space */ + os_mutex_lock(&cluster->lock); free_aux_stack(cluster, exec_env->aux_stack_bottom.bottom); wasm_cluster_del_exec_env(cluster, exec_env); + os_mutex_unlock(&cluster->lock); wasm_exec_env_destroy_internal(exec_env); wasm_runtime_deinstantiate_internal(module_inst, true); @@ -475,15 +477,18 @@ thread_manager_start_routine(void *arg) #endif /* Routine exit */ - /* Free aux stack space */ - free_aux_stack(cluster, exec_env->aux_stack_bottom.bottom); /* Detach the native thread here to ensure the resources are freed */ wasm_cluster_detach_thread(exec_env); #if WASM_ENABLE_DEBUG_INTERP != 0 wasm_cluster_thread_exited(exec_env); #endif - /* Remove and destroy exec_env */ + os_mutex_lock(&cluster->lock); + /* Free aux stack space */ + free_aux_stack(cluster, exec_env->aux_stack_bottom.bottom); + /* Remove and exec_env */ wasm_cluster_del_exec_env(cluster, exec_env); + os_mutex_unlock(&cluster->lock); + /* destroy exec_env */ wasm_exec_env_destroy_internal(exec_env); os_thread_exit(ret); @@ -779,12 +784,14 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval) wasm_cluster_thread_exited(exec_env); #endif /* App exit the thread, free the resources before exit native thread */ - /* Free aux stack space */ - free_aux_stack(cluster, exec_env->aux_stack_bottom.bottom); /* Detach the native thread here to ensure the resources are freed */ wasm_cluster_detach_thread(exec_env); + os_mutex_lock(&cluster->lock); + /* Free aux stack space */ + free_aux_stack(cluster, exec_env->aux_stack_bottom.bottom); /* Remove and destroy exec_env */ wasm_cluster_del_exec_env(cluster, exec_env); + os_mutex_unlock(&cluster->lock); wasm_exec_env_destroy_internal(exec_env); os_thread_exit(retval); @@ -834,7 +841,13 @@ void wasm_cluster_terminate_all(WASMCluster *cluster) { os_mutex_lock(&cluster->lock); + cluster->processing = true; + os_mutex_unlock(&cluster->lock); + traverse_list(&cluster->exec_env_list, terminate_thread_visitor, NULL); + + os_mutex_lock(&cluster->lock); + cluster->processing = false; os_mutex_unlock(&cluster->lock); } @@ -843,8 +856,14 @@ wasm_cluster_terminate_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env) { os_mutex_lock(&cluster->lock); + cluster->processing = true; + os_mutex_unlock(&cluster->lock); + traverse_list(&cluster->exec_env_list, terminate_thread_visitor, (void *)exec_env); + + os_mutex_lock(&cluster->lock); + cluster->processing = false; os_mutex_unlock(&cluster->lock); } @@ -864,7 +883,13 @@ void wams_cluster_wait_for_all(WASMCluster *cluster) { os_mutex_lock(&cluster->lock); + cluster->processing = true; + os_mutex_unlock(&cluster->lock); + traverse_list(&cluster->exec_env_list, wait_for_thread_visitor, NULL); + + os_mutex_lock(&cluster->lock); + cluster->processing = false; os_mutex_unlock(&cluster->lock); } @@ -873,8 +898,14 @@ wasm_cluster_wait_for_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env) { os_mutex_lock(&cluster->lock); + cluster->processing = true; + os_mutex_unlock(&cluster->lock); + traverse_list(&cluster->exec_env_list, wait_for_thread_visitor, (void *)exec_env); + + os_mutex_lock(&cluster->lock); + cluster->processing = false; os_mutex_unlock(&cluster->lock); } @@ -959,9 +990,6 @@ set_exception_visitor(void *node, void *user_data) WASMExecEnv *exec_env = (WASMExecEnv *)user_data; WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env); WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst; - const char *exception = wasm_runtime_get_exception(module_inst); - /* skip "Exception: " */ - exception += 11; if (curr_exec_env != exec_env) { WASMModuleInstance *curr_wasm_inst = @@ -975,6 +1003,20 @@ set_exception_visitor(void *node, void *user_data) } } +static void +clear_exception_visitor(void *node, void *user_data) +{ + WASMExecEnv *exec_env = (WASMExecEnv *)user_data; + WASMExecEnv *curr_exec_env = (WASMExecEnv *)node; + + if (curr_exec_env != exec_env) { + WASMModuleInstance *curr_wasm_inst = + (WASMModuleInstance *)get_module_inst(curr_exec_env); + + curr_wasm_inst->cur_exception[0] = '\0'; + } +} + void wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear) { @@ -983,7 +1025,9 @@ wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear) os_mutex_lock(&cluster->lock); cluster->has_exception = !clear; - traverse_list(&cluster->exec_env_list, set_exception_visitor, exec_env); + traverse_list(&cluster->exec_env_list, + clear ? clear_exception_visitor : set_exception_visitor, + exec_env); os_mutex_unlock(&cluster->lock); } diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index bb245b5a2b..82deb16a52 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -34,7 +34,14 @@ struct WASMCluster { uint32 stack_size; /* Record which segments are occupied */ bool *stack_segment_occupied; + /* When has_exception == true, this cluster will refuse any spawn thread + * requests, this flag can be cleared by calling + * wasm_runtime_clear_exception on instances any thread of this cluster */ bool has_exception; + /* When processing is true, this cluster will refuse any spawn thread + * requests, this is a short-lived state, must be cleared immediately once + * the processing finished */ + bool processing; #if WASM_ENABLE_DEBUG_INTERP != 0 WASMDebugInstance *debug_inst; #endif From d7d78c0a3e2d0a659bad06ad7cd49f4495c42e5e Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 20:58:15 +0800 Subject: [PATCH 16/20] update comments --- core/iwasm/libraries/thread-mgr/thread_manager.c | 4 ++-- core/iwasm/libraries/thread-mgr/thread_manager.h | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 0e1189c464..fe07e22482 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -373,7 +373,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) os_mutex_lock(&cluster->lock); - if (cluster->has_exception) { + if (cluster->has_exception || cluster->processing) { goto fail1; } @@ -510,7 +510,7 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, os_mutex_lock(&cluster->lock); - if (cluster->has_exception) { + if (cluster->has_exception || cluster->processing) { goto fail1; } diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index 82deb16a52..02767a5285 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -34,13 +34,16 @@ struct WASMCluster { uint32 stack_size; /* Record which segments are occupied */ bool *stack_segment_occupied; - /* When has_exception == true, this cluster will refuse any spawn thread + /* When has_exception == true, this cluster should refuse any spawn thread * requests, this flag can be cleared by calling * wasm_runtime_clear_exception on instances any thread of this cluster */ bool has_exception; - /* When processing is true, this cluster will refuse any spawn thread - * requests, this is a short-lived state, must be cleared immediately once - * the processing finished */ + /* When processing is true, this cluster should refuse any spawn thread + * requests. This is a short-lived state, must be cleared immediately once + * the processing finished. + * This is used to avoid dead lock when one thread waiting another thread + * with lock, see wams_cluster_wait_for_all and wasm_cluster_terminate_all + */ bool processing; #if WASM_ENABLE_DEBUG_INTERP != 0 WASMDebugInstance *debug_inst; From f30f90048afa799bf07cb8b36e5f738765cdce87 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Mon, 16 Jan 2023 21:05:40 +0800 Subject: [PATCH 17/20] check return value --- core/iwasm/common/wasm_runtime_common.c | 11 ++++++++--- core/iwasm/libraries/thread-mgr/thread_manager.h | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 393826fbc2..06a370f63b 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2179,6 +2179,8 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm) void wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) { + WASMExecEnv *exec_env = NULL; + if (exception) { snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), "Exception: %s", exception); @@ -2188,9 +2190,12 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) } #if WASM_ENABLE_THREAD_MGR != 0 - wasm_cluster_spread_exception( - wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst), - exception ? false : true); + exec_env = + wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst); + bh_assert(exec_env); + wasm_cluster_spread_exception(exec_env, exception ? false : true); +#else + (void)exec_env; #endif } diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index 02767a5285..657a4abe20 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -36,7 +36,8 @@ struct WASMCluster { bool *stack_segment_occupied; /* When has_exception == true, this cluster should refuse any spawn thread * requests, this flag can be cleared by calling - * wasm_runtime_clear_exception on instances any thread of this cluster */ + * wasm_runtime_clear_exception on instances of any threads of this cluster + */ bool has_exception; /* When processing is true, this cluster should refuse any spawn thread * requests. This is a short-lived state, must be cleared immediately once From 1d6553e84f1f04f605c1e8b1b7cf1e8bb8912ae7 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Tue, 17 Jan 2023 19:05:52 +0800 Subject: [PATCH 18/20] fix spec test issue --- core/iwasm/common/wasm_runtime_common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 06a370f63b..084345692c 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -2192,8 +2192,9 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) #if WASM_ENABLE_THREAD_MGR != 0 exec_env = wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst); - bh_assert(exec_env); - wasm_cluster_spread_exception(exec_env, exception ? false : true); + if (exec_env) { + wasm_cluster_spread_exception(exec_env, exception ? false : true); + } #else (void)exec_env; #endif From 315985bac5d1be38f11e0f1ed2e28d220687cd30 Mon Sep 17 00:00:00 2001 From: Xu Jun <693788454@qq.com> Date: Tue, 17 Jan 2023 22:23:01 +0800 Subject: [PATCH 19/20] fix sgx spec test issue --- core/iwasm/common/wasm_exec_env.c | 5 +++-- core/iwasm/libraries/thread-mgr/thread_manager.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c index ab462d56d6..7939c75909 100644 --- a/core/iwasm/common/wasm_exec_env.c +++ b/core/iwasm/common/wasm_exec_env.c @@ -181,9 +181,10 @@ wasm_exec_env_destroy(WASMExecEnv *exec_env) the stopped thread will be overrided by other threads */ wasm_cluster_thread_exited(exec_env); #endif - os_mutex_lock(&cluster->lock); + /* We have terminated other threads, this is the only alive thread, so + * we don't acquire cluster->lock because the cluster will be destroyed + * inside this function */ wasm_cluster_del_exec_env(cluster, exec_env); - os_mutex_unlock(&cluster->lock); } #endif /* end of WASM_ENABLE_THREAD_MGR */ diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index fe07e22482..a472a2ad3f 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -277,7 +277,7 @@ wasm_cluster_add_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env) return ret; } -/* The caller must lock cluster->lock */ +/* The caller should lock cluster->lock for thread safety */ bool wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env) { From d9390807ffc13763372df533583ad198737b37a5 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Thu, 19 Jan 2023 14:24:15 +0800 Subject: [PATCH 20/20] address PR comments --- core/iwasm/aot/aot_runtime.c | 5 ----- core/iwasm/common/wasm_runtime_common.c | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index ceb71f8f90..5fa5438bd0 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -913,9 +913,6 @@ execute_post_inst_function(AOTModuleInstance *module_inst) NULL); } -extern bool -clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm); - static bool execute_start_function(AOTModuleInstance *module_inst) { @@ -941,8 +938,6 @@ execute_start_function(AOTModuleInstance *module_inst) u.f(exec_env); wasm_exec_env_destroy(exec_env); - (void)clear_wasi_proc_exit_exception( - (WASMModuleInstanceCommon *)module_inst); return !aot_get_exception(module_inst); } diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 084345692c..aed92edf2a 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1743,7 +1743,7 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env, } #endif -bool +static bool clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm) { #if WASM_ENABLE_LIBC_WASI != 0