Skip to content

Commit 382d52f

Browse files
authored
Stop abusing shared memory lock to protect exception (#2509)
Use a separate global lock instead. Fixes: #2407
1 parent 53d7027 commit 382d52f

File tree

4 files changed

+77
-78
lines changed

4 files changed

+77
-78
lines changed

core/iwasm/common/wasm_runtime_common.c

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2377,32 +2377,22 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm)
23772377
void
23782378
wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
23792379
{
2380-
WASMExecEnv *exec_env = NULL;
2381-
2382-
#if WASM_ENABLE_SHARED_MEMORY != 0
2383-
if (module_inst->memory_count > 0)
2384-
shared_memory_lock(module_inst->memories[0]);
2385-
#endif
2380+
exception_lock(module_inst);
23862381
if (exception) {
23872382
snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception),
23882383
"Exception: %s", exception);
23892384
}
23902385
else {
23912386
module_inst->cur_exception[0] = '\0';
23922387
}
2393-
#if WASM_ENABLE_SHARED_MEMORY != 0
2394-
if (module_inst->memory_count > 0)
2395-
shared_memory_unlock(module_inst->memories[0]);
2396-
#endif
2388+
exception_unlock(module_inst);
23972389

23982390
#if WASM_ENABLE_THREAD_MGR != 0
2399-
exec_env =
2391+
WASMExecEnv *exec_env =
24002392
wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst);
24012393
if (exec_env) {
2402-
wasm_cluster_spread_exception(exec_env, exception ? false : true);
2394+
wasm_cluster_spread_exception(exec_env, exception);
24032395
}
2404-
#else
2405-
(void)exec_env;
24062396
#endif
24072397
}
24082398

@@ -2453,10 +2443,7 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf)
24532443
{
24542444
bool has_exception = false;
24552445

2456-
#if WASM_ENABLE_SHARED_MEMORY != 0
2457-
if (module_inst->memory_count > 0)
2458-
shared_memory_lock(module_inst->memories[0]);
2459-
#endif
2446+
exception_lock(module_inst);
24602447
if (module_inst->cur_exception[0] != '\0') {
24612448
/* NULL is passed if the caller is not interested in getting the
24622449
* exception content, but only in knowing if an exception has been
@@ -2468,10 +2455,7 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf)
24682455
sizeof(module_inst->cur_exception));
24692456
has_exception = true;
24702457
}
2471-
#if WASM_ENABLE_SHARED_MEMORY != 0
2472-
if (module_inst->memory_count > 0)
2473-
shared_memory_unlock(module_inst->memories[0]);
2474-
#endif
2458+
exception_unlock(module_inst);
24752459

24762460
return has_exception;
24772461
}

core/iwasm/interpreter/wasm_runtime.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,16 @@ void
668668
wasm_propagate_wasi_args(WASMModule *module);
669669
#endif
670670

671+
#if WASM_ENABLE_THREAD_MGR != 0
672+
void
673+
exception_lock(WASMModuleInstance *module_inst);
674+
void
675+
exception_unlock(WASMModuleInstance *module_inst);
676+
#else
677+
#define exception_lock(module_inst) (void)(module_inst)
678+
#define exception_unlock(module_inst) (void)(module_inst)
679+
#endif
680+
671681
#ifdef __cplusplus
672682
}
673683
#endif

core/iwasm/libraries/thread-mgr/thread_manager.c

Lines changed: 60 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616
#include "debug_engine.h"
1717
#endif
1818

19-
#if WASM_ENABLE_SHARED_MEMORY != 0
20-
#include "wasm_shared_memory.h"
21-
#endif
22-
2319
typedef struct {
2420
bh_list_link l;
2521
void (*destroy_cb)(WASMCluster *);
@@ -32,6 +28,8 @@ static bh_list cluster_list_head;
3228
static bh_list *const cluster_list = &cluster_list_head;
3329
static korp_mutex cluster_list_lock;
3430

31+
static korp_mutex _exception_lock;
32+
3533
typedef void (*list_visitor)(void *, void *);
3634

3735
static uint32 cluster_max_thread_num = CLUSTER_MAX_THREAD_NUM;
@@ -52,6 +50,10 @@ thread_manager_init()
5250
return false;
5351
if (os_mutex_init(&cluster_list_lock) != 0)
5452
return false;
53+
if (os_mutex_init(&_exception_lock) != 0) {
54+
os_mutex_destroy(&cluster_list_lock);
55+
return false;
56+
}
5557
return true;
5658
}
5759

@@ -66,6 +68,7 @@ thread_manager_destroy()
6668
cluster = next;
6769
}
6870
wasm_cluster_cancel_all_callbacks();
71+
os_mutex_destroy(&_exception_lock);
6972
os_mutex_destroy(&cluster_list_lock);
7073
}
7174

@@ -1240,72 +1243,56 @@ wasm_cluster_resume_all(WASMCluster *cluster)
12401243
os_mutex_unlock(&cluster->lock);
12411244
}
12421245

1246+
struct spread_exception_data {
1247+
WASMExecEnv *skip;
1248+
const char *exception;
1249+
};
1250+
12431251
static void
12441252
set_exception_visitor(void *node, void *user_data)
12451253
{
1246-
WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
1247-
WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
1248-
WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env);
1249-
WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst;
1250-
1251-
if (curr_exec_env != exec_env) {
1252-
WASMModuleInstance *curr_wasm_inst =
1253-
(WASMModuleInstance *)get_module_inst(curr_exec_env);
1254-
1255-
/* Only spread non "wasi proc exit" exception */
1256-
#if WASM_ENABLE_SHARED_MEMORY != 0
1257-
if (curr_wasm_inst->memory_count > 0)
1258-
shared_memory_lock(curr_wasm_inst->memories[0]);
1259-
#endif
1260-
if (!strstr(wasm_inst->cur_exception, "wasi proc exit")) {
1261-
bh_memcpy_s(curr_wasm_inst->cur_exception,
1262-
sizeof(curr_wasm_inst->cur_exception),
1263-
wasm_inst->cur_exception,
1264-
sizeof(wasm_inst->cur_exception));
1254+
const struct spread_exception_data *data = user_data;
1255+
WASMExecEnv *exec_env = (WASMExecEnv *)node;
1256+
1257+
if (exec_env != data->skip) {
1258+
WASMModuleInstance *wasm_inst =
1259+
(WASMModuleInstance *)get_module_inst(exec_env);
1260+
1261+
exception_lock(wasm_inst);
1262+
if (data->exception != NULL) {
1263+
/* Only spread non "wasi proc exit" exception */
1264+
if (strcmp(data->exception, "wasi proc exit")) {
1265+
snprintf(wasm_inst->cur_exception,
1266+
sizeof(wasm_inst->cur_exception), "Exception: %s",
1267+
data->exception);
1268+
}
12651269
}
1266-
#if WASM_ENABLE_SHARED_MEMORY != 0
1267-
if (curr_wasm_inst->memory_count > 0)
1268-
shared_memory_unlock(curr_wasm_inst->memories[0]);
1269-
#endif
1270+
else {
1271+
wasm_inst->cur_exception[0] = '\0';
1272+
}
1273+
exception_unlock(wasm_inst);
12701274

12711275
/* Terminate the thread so it can exit from dead loops */
1272-
set_thread_cancel_flags(curr_exec_env);
1273-
}
1274-
}
1275-
1276-
static void
1277-
clear_exception_visitor(void *node, void *user_data)
1278-
{
1279-
WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
1280-
WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
1281-
1282-
if (curr_exec_env != exec_env) {
1283-
WASMModuleInstance *curr_wasm_inst =
1284-
(WASMModuleInstance *)get_module_inst(curr_exec_env);
1285-
1286-
#if WASM_ENABLE_SHARED_MEMORY != 0
1287-
if (curr_wasm_inst->memory_count > 0)
1288-
shared_memory_lock(curr_wasm_inst->memories[0]);
1289-
#endif
1290-
curr_wasm_inst->cur_exception[0] = '\0';
1291-
#if WASM_ENABLE_SHARED_MEMORY != 0
1292-
if (curr_wasm_inst->memory_count > 0)
1293-
shared_memory_unlock(curr_wasm_inst->memories[0]);
1294-
#endif
1276+
if (data->exception != NULL) {
1277+
set_thread_cancel_flags(exec_env);
1278+
}
12951279
}
12961280
}
12971281

12981282
void
1299-
wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear)
1283+
wasm_cluster_spread_exception(WASMExecEnv *exec_env, const char *exception)
13001284
{
1285+
const bool has_exception = exception != NULL;
13011286
WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
13021287
bh_assert(cluster);
13031288

1289+
struct spread_exception_data data;
1290+
data.skip = exec_env;
1291+
data.exception = exception;
1292+
13041293
os_mutex_lock(&cluster->lock);
1305-
cluster->has_exception = !clear;
1306-
traverse_list(&cluster->exec_env_list,
1307-
clear ? clear_exception_visitor : set_exception_visitor,
1308-
exec_env);
1294+
cluster->has_exception = has_exception;
1295+
traverse_list(&cluster->exec_env_list, set_exception_visitor, &data);
13091296
os_mutex_unlock(&cluster->lock);
13101297
}
13111298

@@ -1353,3 +1340,21 @@ wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
13531340

13541341
return is_thread_terminated;
13551342
}
1343+
1344+
void
1345+
exception_lock(WASMModuleInstance *module_inst)
1346+
{
1347+
/*
1348+
* Note: this lock could be per module instance if desirable.
1349+
* We can revisit on AOT version bump.
1350+
* It probably doesn't matter though because the exception handling
1351+
* logic should not be executed too frequently anyway.
1352+
*/
1353+
os_mutex_lock(&_exception_lock);
1354+
}
1355+
1356+
void
1357+
exception_unlock(WASMModuleInstance *module_inst)
1358+
{
1359+
os_mutex_unlock(&_exception_lock);
1360+
}

core/iwasm/libraries/thread-mgr/thread_manager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ WASMExecEnv *
139139
wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst);
140140

141141
void
142-
wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear);
142+
wasm_cluster_spread_exception(WASMExecEnv *exec_env, const char *exception);
143143

144144
WASMExecEnv *
145145
wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env);

0 commit comments

Comments
 (0)