From 71d43f3ca18b96c983d0fa8ca45ea658d6f9ee4a Mon Sep 17 00:00:00 2001 From: Enrico Loparco Date: Fri, 5 May 2023 03:20:05 +0200 Subject: [PATCH] Return error when exception was raised after main thread finishes (#2169) Currently, if a thread is spawned and raises an exception after the main thread has finished, iwasm returns with success instead of returning 1 (i.e. error). Since wasm_runtime_get_wasi_exit_code waits for all threads to finish and only returns the wasi exit code, this PR performs the exception check again and returns error if an exception was raised. --- .../test/trap_after_main_thread_finishes.c | 44 +++++++++++++++++++ .../test/trap_after_main_thread_finishes.json | 3 ++ product-mini/platforms/posix/main.c | 6 ++- product-mini/platforms/windows/main.c | 6 ++- 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c create mode 100644 core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json diff --git a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c new file mode 100644 index 0000000000..69e125d407 --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef __wasi__ +#error This example only compiles to WASM/WASI target +#endif + +#include +#include +#include + +#include "wasi_thread_start.h" + +enum CONSTANTS { + SECOND = 1000 * 1000 * 1000, /* 1 second */ + TIMEOUT = 1LL * SECOND +}; + +typedef struct { + start_args_t base; +} shared_t; + +void +__wasi_thread_start_C(int thread_id, int *start_arg) +{ + /* Wait so that the exception is raised after the main thread has finished + * already */ + __builtin_wasm_memory_atomic_wait32(NULL, 0, TIMEOUT); + __builtin_trap(); +} + +int +main(int argc, char **argv) +{ + shared_t data = { 0 }; + + assert(start_args_init(&data.base)); + int thread_id = __wasi_thread_spawn(&data); + assert(thread_id > 0 && "Thread creation failed"); + + return EXIT_SUCCESS; +} diff --git a/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json new file mode 100644 index 0000000000..9dc1e30d2b --- /dev/null +++ b/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json @@ -0,0 +1,3 @@ +{ + "exit_code": 1 +} diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 8727ed3895..2e96ccddd6 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -745,8 +745,12 @@ main(int argc, char *argv[]) #if WASM_ENABLE_LIBC_WASI != 0 if (ret == 0) { - /* propagate wasi exit code. */ + /* wait for threads to finish and propagate wasi exit code. */ ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst); + if (wasm_runtime_get_exception(wasm_module_inst)) { + /* got an exception in spawned thread */ + ret = 1; + } } #endif diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 05647b5dbc..26fa7dcc96 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -549,8 +549,12 @@ main(int argc, char *argv[]) #if WASM_ENABLE_LIBC_WASI != 0 if (ret == 0) { - /* propagate wasi exit code. */ + /* wait for threads to finish and propagate wasi exit code. */ ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst); + if (wasm_runtime_get_exception(wasm_module_inst)) { + /* got an exception in spawned thread */ + ret = 1; + } } #endif