Răsfoiți Sursa

Add wasm_runtime_get_wasi_exit_code (#1748)

Refer to https://github.com/bytecodealliance/wasm-micro-runtime/issues/1738
YAMAMOTO Takashi 3 ani în urmă
părinte
comite
310feb9696

+ 14 - 6
core/iwasm/common/wasm_runtime_common.c

@@ -2675,17 +2675,18 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
                        char *argv[], uint32 argc, int stdinfd, int stdoutfd,
                        int stderrfd, char *error_buf, uint32 error_buf_size)
 {
-    uvwasi_t *uvwasi = NULL;
+    WASIContext *ctx;
+    uvwasi_t *uvwasi;
     uvwasi_options_t init_options;
     const char **envp = NULL;
     uint64 total_size;
     uint32 i;
     bool ret = false;
 
-    uvwasi = runtime_malloc(sizeof(uvwasi_t), module_inst, error_buf,
-                            error_buf_size);
-    if (!uvwasi)
+    ctx = runtime_malloc(sizeof(*ctx), module_inst, error_buf, error_buf_size);
+    if (!ctx)
         return false;
+    uvwasi = &ctx->uvwasi;
 
     /* Setup the initialization options */
     uvwasi_options_init(&init_options);
@@ -2733,7 +2734,7 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
         goto fail;
     }
 
-    wasm_runtime_set_wasi_ctx(module_inst, uvwasi);
+    wasm_runtime_set_wasi_ctx(module_inst, ctx);
 
     ret = true;
 
@@ -2863,12 +2864,19 @@ wasm_runtime_destroy_wasi(WASMModuleInstanceCommon *module_inst)
     WASIContext *wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
 
     if (wasi_ctx) {
-        uvwasi_destroy(wasi_ctx);
+        uvwasi_destroy(&wasi_ctx->uvwasi);
         wasm_runtime_free(wasi_ctx);
     }
 }
 #endif
 
+uint32_t
+wasm_runtime_get_wasi_exit_code(WASMModuleInstanceCommon *module_inst)
+{
+    WASIContext *wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
+    return wasi_ctx->exit_code;
+}
+
 WASIContext *
 wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
 {

+ 9 - 1
core/iwasm/common/wasm_runtime_common.h

@@ -369,9 +369,13 @@ typedef struct WASIContext {
     char **argv_list;
     char *env_buf;
     char **env_list;
+    uint32_t exit_code;
 } WASIContext;
 #else
-typedef uvwasi_t WASIContext;
+typedef struct WASIContext {
+    uvwasi_t uvwasi;
+    uint32_t exit_code;
+} WASIContext;
 #endif
 #endif
 
@@ -768,6 +772,10 @@ wasm_runtime_is_wasi_mode(WASMModuleInstanceCommon *module_inst);
 WASM_RUNTIME_API_EXTERN WASMFunctionInstanceCommon *
 wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst);
 
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_runtime_get_wasi_exit_code(WASMModuleInstanceCommon *module_inst);
+
 bool
 wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
                        const char *dir_list[], uint32 dir_count,

+ 12 - 0
core/iwasm/include/wasm_export.h

@@ -450,6 +450,18 @@ wasm_runtime_is_wasi_mode(wasm_module_inst_t module_inst);
 WASM_RUNTIME_API_EXTERN wasm_function_inst_t
 wasm_runtime_lookup_wasi_start_function(wasm_module_inst_t module_inst);
 
+/**
+ * Get WASI exit code.
+ *
+ * After a WASI command completed its execution, an embedder can
+ * call this function to get its exit code. (that is, the value given
+ * to proc_exit.)
+ *
+ * @param module_inst the module instance
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_runtime_get_wasi_exit_code(wasm_module_inst_t module_inst);
+
 /**
  * Lookup an exported function in the WASM module instance.
  *

+ 17 - 3
core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c

@@ -11,9 +11,6 @@
 #define get_module_inst(exec_env) \
     wasm_runtime_get_module_inst(exec_env)
 
-#define get_wasi_ctx(module_inst) \
-    wasm_runtime_get_wasi_ctx(module_inst)
-
 #define validate_app_addr(offset, size) \
     wasm_runtime_validate_app_addr(module_inst, offset, size)
 
@@ -72,9 +69,24 @@ typedef struct iovec_app {
     uint32 buf_len;
 } iovec_app_t;
 
+typedef struct WASIContext {
+    uvwasi_t uvwasi;
+    uint32_t exit_code;
+} WASIContext;
+
 void *
 wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst);
 
+static uvwasi_t *
+get_wasi_ctx(wasm_module_inst_t module_inst)
+{
+    WASIContext *ctx = wasm_runtime_get_wasi_ctx(module_inst);
+    if (ctx == NULL) {
+        return NULL;
+    }
+    return &ctx->uvwasi;
+}
+
 static wasi_errno_t
 wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf)
 {
@@ -924,10 +936,12 @@ static void
 wasi_proc_exit(wasm_exec_env_t exec_env, wasi_exitcode_t rval)
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
+    WASIContext *wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
     /* Here throwing exception is just to let wasm app exit,
        the upper layer should clear the exception and return
        as normal */
     wasm_runtime_set_exception(module_inst, "wasi proc exit");
+    wasi_ctx->exit_code = rval;
 }
 
 static wasi_errno_t

+ 3 - 0
core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c

@@ -57,6 +57,7 @@ typedef struct WASIContext {
     char **argv_list;
     char *env_buf;
     char **env_list;
+    uint32_t exit_code;
 } * wasi_ctx_t;
 
 wasi_ctx_t
@@ -980,10 +981,12 @@ static void
 wasi_proc_exit(wasm_exec_env_t exec_env, wasi_exitcode_t rval)
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
+    wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
     /* Here throwing exception is just to let wasm app exit,
        the upper layer should clear the exception and return
        as normal */
     wasm_runtime_set_exception(module_inst, "wasi proc exit");
+    wasi_ctx->exit_code = rval;
 }
 
 static wasi_errno_t

+ 23 - 8
product-mini/platforms/posix/main.c

@@ -86,7 +86,7 @@ app_instance_main(wasm_module_inst_t module_inst)
     wasm_application_execute_main(module_inst, app_argc, app_argv);
     if ((exception = wasm_runtime_get_exception(module_inst)))
         printf("%s\n", exception);
-    return NULL;
+    return exception;
 }
 
 static void *
@@ -96,7 +96,7 @@ app_instance_func(wasm_module_inst_t module_inst, const char *func_name)
                                   app_argv + 1);
     /* The result of wasm function or exception info was output inside
        wasm_application_execute_func(), here we don't output them again. */
-    return NULL;
+    return wasm_runtime_get_exception(module_inst);
 }
 
 /**
@@ -643,14 +643,29 @@ main(int argc, char *argv[])
     }
 #endif
 
-    if (is_repl_mode)
+    ret = 0;
+    if (is_repl_mode) {
         app_instance_repl(wasm_module_inst);
-    else if (func_name)
-        app_instance_func(wasm_module_inst, func_name);
-    else
-        app_instance_main(wasm_module_inst);
+    }
+    else if (func_name) {
+        if (app_instance_func(wasm_module_inst, func_name)) {
+            /* got an exception */
+            ret = 1;
+        }
+    }
+    else {
+        if (app_instance_main(wasm_module_inst)) {
+            /* got an exception */
+            ret = 1;
+        }
+    }
 
-    ret = 0;
+#if WASM_ENABLE_LIBC_WASI != 0
+    if (ret == 0) {
+        /* propagate wasi exit code. */
+        ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst);
+    }
+#endif
 
 #if WASM_ENABLE_DEBUG_INTERP != 0
 fail4:

+ 23 - 8
product-mini/platforms/windows/main.c

@@ -63,7 +63,7 @@ app_instance_main(wasm_module_inst_t module_inst)
     wasm_application_execute_main(module_inst, app_argc, app_argv);
     if ((exception = wasm_runtime_get_exception(module_inst)))
         printf("%s\n", exception);
-    return NULL;
+    return exception;
 }
 
 static void *
@@ -73,7 +73,7 @@ app_instance_func(wasm_module_inst_t module_inst, const char *func_name)
                                   app_argv + 1);
     /* The result of wasm function or exception info was output inside
        wasm_application_execute_func(), here we don't output them again. */
-    return NULL;
+    return wasm_runtime_get_exception(module_inst);
 }
 
 /**
@@ -451,14 +451,29 @@ main(int argc, char *argv[])
     }
 #endif
 
-    if (is_repl_mode)
+    ret = 0;
+    if (is_repl_mode) {
         app_instance_repl(wasm_module_inst);
-    else if (func_name)
-        app_instance_func(wasm_module_inst, func_name);
-    else
-        app_instance_main(wasm_module_inst);
+    }
+    else if (func_name) {
+        if (app_instance_func(wasm_module_inst, func_name)) {
+            /* got an exception */
+            ret = 1;
+        }
+    }
+    else {
+        if (app_instance_main(wasm_module_inst)) {
+            /* got an exception */
+            ret = 1;
+        }
+    }
 
-    ret = 0;
+#if WASM_ENABLE_LIBC_WASI != 0
+    if (ret == 0) {
+        /* propagate wasi exit code. */
+        ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst);
+    }
+#endif
 
 #if WASM_ENABLE_DEBUG_INTERP != 0
 fail4: