Skip to content

Commit ff25110

Browse files
authored
Return stack frames of crashed thread when using wasm-c-api (#2908)
When using the wasm-c-api and there's a trap, `wasm_func_call()` returns a `wasm_trap_t *` object. No matter which thread crashes, the trap contains the stack frames of the main thread. With this PR, when there's an exception, the stack frames of the thread where the exception occurs are stored into the thread cluster. `wasm_func_call()` can then return those stack frames.
1 parent b21f17d commit ff25110

File tree

4 files changed

+73
-8
lines changed

4 files changed

+73
-8
lines changed

core/iwasm/common/wasm_c_api.c

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,10 +1921,26 @@ wasm_frame_func_offset(const wasm_frame_t *frame)
19211921
return frame ? frame->func_offset : 0;
19221922
}
19231923

1924+
void
1925+
wasm_frame_vec_clone_internal(Vector *src, Vector *out)
1926+
{
1927+
bh_assert(src->num_elems != 0 && src->data);
1928+
1929+
bh_vector_destroy(out);
1930+
if (!bh_vector_init(out, src->num_elems, sizeof(WASMCApiFrame), false)) {
1931+
bh_vector_destroy(out);
1932+
return;
1933+
}
1934+
1935+
bh_memcpy_s(out->data, src->num_elems * sizeof(WASMCApiFrame), src->data,
1936+
src->num_elems * sizeof(WASMCApiFrame));
1937+
out->num_elems = src->num_elems;
1938+
}
1939+
19241940
static wasm_trap_t *
19251941
wasm_trap_new_internal(wasm_store_t *store,
19261942
WASMModuleInstanceCommon *inst_comm_rt,
1927-
const char *error_info)
1943+
const char *error_info, Vector *cluster_frames)
19281944
{
19291945
wasm_trap_t *trap;
19301946
#if WASM_ENABLE_DUMP_CALL_STACK != 0
@@ -1954,7 +1970,9 @@ wasm_trap_new_internal(wasm_store_t *store,
19541970

19551971
/* fill in frames */
19561972
#if WASM_ENABLE_DUMP_CALL_STACK != 0
1957-
trap->frames = ((WASMModuleInstance *)inst_comm_rt)->frames;
1973+
trap->frames = cluster_frames
1974+
? cluster_frames
1975+
: ((WASMModuleInstance *)inst_comm_rt)->frames;
19581976

19591977
if (trap->frames) {
19601978
/* fill in instances */
@@ -2065,10 +2083,7 @@ wasm_trap_trace(const wasm_trap_t *trap, own wasm_frame_vec_t *out)
20652083
}
20662084

20672085
for (i = 0; i < trap->frames->num_elems; i++) {
2068-
wasm_frame_t *frame;
2069-
2070-
frame = ((wasm_frame_t *)trap->frames->data) + i;
2071-
2086+
wasm_frame_t *frame = ((wasm_frame_t *)trap->frames->data) + i;
20722087
if (!(out->data[i] =
20732088
wasm_frame_new(frame->instance, frame->module_offset,
20742089
frame->func_index, frame->func_offset))) {
@@ -3252,6 +3267,7 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
32523267
WASMFunctionInstanceCommon *func_comm_rt = NULL;
32533268
WASMExecEnv *exec_env = NULL;
32543269
size_t param_count, result_count, alloc_count;
3270+
Vector *cluster_frames = NULL;
32553271

32563272
bh_assert(func && func->type);
32573273

@@ -3364,9 +3380,20 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
33643380
if (argv != argv_buf)
33653381
wasm_runtime_free(argv);
33663382

3367-
return wasm_trap_new_internal(
3383+
#if WASM_ENABLE_DUMP_CALL_STACK != 0 && WASM_ENABLE_THREAD_MGR != 0
3384+
WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
3385+
cluster_frames = &cluster->exception_frames;
3386+
wasm_cluster_traverse_lock(exec_env);
3387+
#endif
3388+
3389+
wasm_trap_t *trap = wasm_trap_new_internal(
33683390
func->store, func->inst_comm_rt,
3369-
wasm_runtime_get_exception(func->inst_comm_rt));
3391+
wasm_runtime_get_exception(func->inst_comm_rt), cluster_frames);
3392+
3393+
#if WASM_ENABLE_DUMP_CALL_STACK != 0 && WASM_ENABLE_THREAD_MGR != 0
3394+
wasm_cluster_traverse_unlock(exec_env);
3395+
#endif
3396+
return trap;
33703397
}
33713398

33723399
size_t

core/iwasm/common/wasm_c_api_internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,4 +240,7 @@ wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt,
240240
wasm_table_t *
241241
wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt,
242242
WASMModuleInstanceCommon *inst_comm_rt);
243+
244+
void
245+
wasm_frame_vec_clone_internal(Vector *src, Vector *out);
243246
#endif /* _WASM_C_API_INTERNAL_H */

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
#include "thread_manager.h"
7+
#include "../common/wasm_c_api_internal.h"
78

89
#if WASM_ENABLE_INTERP != 0
910
#include "../interpreter/wasm_runtime.h"
@@ -370,6 +371,10 @@ wasm_cluster_destroy(WASMCluster *cluster)
370371
wasm_debug_instance_destroy(cluster);
371372
#endif
372373

374+
#if WASM_ENABLE_DUMP_CALL_STACK != 0
375+
bh_vector_destroy(&cluster->exception_frames);
376+
#endif
377+
373378
wasm_runtime_free(cluster);
374379
}
375380

@@ -1321,6 +1326,29 @@ wasm_cluster_set_exception(WASMExecEnv *exec_env, const char *exception)
13211326
data.exception = exception;
13221327

13231328
os_mutex_lock(&cluster->lock);
1329+
#if WASM_ENABLE_DUMP_CALL_STACK != 0
1330+
if (has_exception) {
1331+
/* Save the stack frames of the crashed thread into the cluster */
1332+
WASMModuleInstance *module_inst =
1333+
(WASMModuleInstance *)get_module_inst(exec_env);
1334+
1335+
#if WASM_ENABLE_INTERP != 0
1336+
if (module_inst->module_type == Wasm_Module_Bytecode
1337+
&& wasm_interp_create_call_stack(exec_env)) {
1338+
wasm_frame_vec_clone_internal(module_inst->frames,
1339+
&cluster->exception_frames);
1340+
}
1341+
#endif
1342+
1343+
#if WASM_ENABLE_AOT != 0
1344+
if (module_inst->module_type == Wasm_Module_AoT
1345+
&& aot_create_call_stack(exec_env)) {
1346+
wasm_frame_vec_clone_internal(module_inst->frames,
1347+
&cluster->exception_frames);
1348+
}
1349+
#endif
1350+
}
1351+
#endif /* WASM_ENABLE_DUMP_CALL_STACK != 0 */
13241352
cluster->has_exception = has_exception;
13251353
traverse_list(&cluster->exec_env_list, set_exception_visitor, &data);
13261354
os_mutex_unlock(&cluster->lock);

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ struct WASMCluster {
5151
#if WASM_ENABLE_DEBUG_INTERP != 0
5252
WASMDebugInstance *debug_inst;
5353
#endif
54+
55+
#if WASM_ENABLE_DUMP_CALL_STACK != 0
56+
/* When an exception occurs in a thread, the stack frames of that thread are
57+
* saved into the cluster
58+
*/
59+
Vector exception_frames;
60+
#endif
5461
};
5562

5663
void

0 commit comments

Comments
 (0)