davecramer added the bug label to Issue #10167.
davecramer opened issue #10167:
Thanks for filing a bug report! Please fill out the TODOs below.
Note: if you want to report a security issue, please read our security policy!
Test Case
With the following python
def talk(message): return "Talk " + message def main(): print(talk("Hello World")) return 0 if __name__ == "__main__": main()
compiled to wasm using py2wasm
int main() { // Set up our context wasm_engine_t *engine = wasm_engine_new(); assert(engine != NULL); wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL); assert(store != NULL); wasmtime_context_t *context = wasmtime_store_context(store); // Create a linker with WASI functions defined wasmtime_linker_t *linker = wasmtime_linker_new(engine); wasmtime_error_t *error = wasmtime_linker_define_wasi(linker); if (error != NULL) exit_with_error("failed to link wasi", error, NULL); wasm_byte_vec_t wasm; // Load our input file to parse it next FILE *file = fopen("wasm/test.wasm", "rb"); if (!file) { printf("> Error loading file!\n"); exit(1); } fseek(file, 0L, SEEK_END); size_t file_size = ftell(file); wasm_byte_vec_new_uninitialized(&wasm, file_size); fseek(file, 0L, SEEK_SET); if (fread(wasm.data, file_size, 1, file) != 1) { printf("> Error loading module!\n"); exit(1); } fclose(file); // Compile our modules wasmtime_module_t *module = NULL; error = wasmtime_module_new(engine, (uint8_t *)wasm.data, wasm.size, &module); if (!module) exit_with_error("failed to compile module", error, NULL); wasm_byte_vec_delete(&wasm); // Instantiate wasi wasi_config_t *wasi_config = wasi_config_new(); assert(wasi_config); wasi_config_inherit_argv(wasi_config); wasi_config_inherit_env(wasi_config); wasi_config_inherit_stdin(wasi_config); wasi_config_inherit_stdout(wasi_config); wasi_config_inherit_stderr(wasi_config); wasm_trap_t *trap = NULL; error = wasmtime_context_set_wasi(context, wasi_config); if (error != NULL) exit_with_error("failed to instantiate WASI", error, NULL); // Instantiate the module error = wasmtime_linker_module(linker, context, "", 0, module); if (error != NULL) exit_with_error("failed to instantiate module", error, NULL); // Run it. wasmtime_func_t func; error = wasmtime_linker_get_default(linker, context, "main", 0, &func); if (error != NULL) exit_with_error("failed to locate default export for module", error, NULL); error = wasmtime_func_call(context, &func, NULL, 0, NULL, 0, &trap); if (error != NULL || trap != NULL){ exit_with_error("error calling default export", error, trap); } // Clean up after ourselves at this point wasmtime_module_delete(module); wasmtime_store_delete(store); wasm_engine_delete(engine); return 0; } static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap) { fprintf(stderr, "error: %s\n", message); wasm_byte_vec_t error_message; if (error != NULL) { wasmtime_error_message(error, &error_message); wasmtime_error_delete(error); } else { wasm_trap_message(trap, &error_message); wasm_trap_delete(trap); } fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data); wasm_byte_vec_delete(&error_message); exit(1); }
TODO: upload Wasm file here
I get the errorTalk Hello World error: error calling default export error while executing at wasm backtrace: 0: 0x32a019 - <unknown>!__wasi_proc_exit 1: 0x3286df - <unknown>!_Exit 2: 0x33301f - <unknown>!exit 3: 0x16698d - <unknown>!Py_Exit 4: 0x34b2dc - <unknown>!main 5: 0x329c22 - <unknown>!__main_void 6: 0x5002 - <unknown>!_start note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information Caused by: Exited with i32 exit status 0
Versions and Environment
Wasmtime version or commit:
29.0.0Operating system: macos Sonoma 14.7.2
Architecture: ARM
davecramer edited issue #10167:
Test Case
With the following python
def talk(message): return "Talk " + message def main(): print(talk("Hello World")) return 0 if __name__ == "__main__": main()
compiled to wasm using py2wasm
int main() { // Set up our context wasm_engine_t *engine = wasm_engine_new(); assert(engine != NULL); wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL); assert(store != NULL); wasmtime_context_t *context = wasmtime_store_context(store); // Create a linker with WASI functions defined wasmtime_linker_t *linker = wasmtime_linker_new(engine); wasmtime_error_t *error = wasmtime_linker_define_wasi(linker); if (error != NULL) exit_with_error("failed to link wasi", error, NULL); wasm_byte_vec_t wasm; // Load our input file to parse it next FILE *file = fopen("wasm/test.wasm", "rb"); if (!file) { printf("> Error loading file!\n"); exit(1); } fseek(file, 0L, SEEK_END); size_t file_size = ftell(file); wasm_byte_vec_new_uninitialized(&wasm, file_size); fseek(file, 0L, SEEK_SET); if (fread(wasm.data, file_size, 1, file) != 1) { printf("> Error loading module!\n"); exit(1); } fclose(file); // Compile our modules wasmtime_module_t *module = NULL; error = wasmtime_module_new(engine, (uint8_t *)wasm.data, wasm.size, &module); if (!module) exit_with_error("failed to compile module", error, NULL); wasm_byte_vec_delete(&wasm); // Instantiate wasi wasi_config_t *wasi_config = wasi_config_new(); assert(wasi_config); wasi_config_inherit_argv(wasi_config); wasi_config_inherit_env(wasi_config); wasi_config_inherit_stdin(wasi_config); wasi_config_inherit_stdout(wasi_config); wasi_config_inherit_stderr(wasi_config); wasm_trap_t *trap = NULL; error = wasmtime_context_set_wasi(context, wasi_config); if (error != NULL) exit_with_error("failed to instantiate WASI", error, NULL); // Instantiate the module error = wasmtime_linker_module(linker, context, "", 0, module); if (error != NULL) exit_with_error("failed to instantiate module", error, NULL); // Run it. wasmtime_func_t func; error = wasmtime_linker_get_default(linker, context, "main", 0, &func); if (error != NULL) exit_with_error("failed to locate default export for module", error, NULL); error = wasmtime_func_call(context, &func, NULL, 0, NULL, 0, &trap); if (error != NULL || trap != NULL){ exit_with_error("error calling default export", error, trap); } // Clean up after ourselves at this point wasmtime_module_delete(module); wasmtime_store_delete(store); wasm_engine_delete(engine); return 0; } static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap) { fprintf(stderr, "error: %s\n", message); wasm_byte_vec_t error_message; if (error != NULL) { wasmtime_error_message(error, &error_message); wasmtime_error_delete(error); } else { wasm_trap_message(trap, &error_message); wasm_trap_delete(trap); } fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data); wasm_byte_vec_delete(&error_message); exit(1); }
TODO: upload Wasm file here
I get the errorTalk Hello World error: error calling default export error while executing at wasm backtrace: 0: 0x32a019 - <unknown>!__wasi_proc_exit 1: 0x3286df - <unknown>!_Exit 2: 0x33301f - <unknown>!exit 3: 0x16698d - <unknown>!Py_Exit 4: 0x34b2dc - <unknown>!main 5: 0x329c22 - <unknown>!__main_void 6: 0x5002 - <unknown>!_start note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information Caused by: Exited with i32 exit status 0
Versions and Environment
Wasmtime version or commit:
29.0.0Operating system: macos Sonoma 14.7.2
Architecture: ARM
bjorn3 commented on issue #10167:
The wasi_proc_exit syscall works by throwing a trap with the exit code. In Rust you can downcast the trap to the wasi exit code type, but I don't think the C API supports this.
bjorn3 edited a comment on issue #10167:
The wasi_proc_exit syscall works by throwing a trap with the exit code. In Rust you can downcast the trap to the wasi exit code type, but I don't think the C API supports this.
davecramer commented on issue #10167:
Interesting as it is more or less from the examples
Thanks
Dave Cramer
On Sun, Feb 2, 2025 at 5:18 AM bjorn3 @.***> wrote:
The wasi_proc_exit syscall works by throwing a trap with the exit code. In
Rust you can downcast the trap to the wasi exit code type, but I don't
think the C API supports this.—
Reply to this email directly, view it on GitHub
<https://github.com/bytecodealliance/wasmtime/issues/10167#issuecomment-2629331747>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADDH5QPPT7ERETPV7KLM332NXWHLAVCNFSM6AAAAABWKAIFZOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDMMRZGMZTCNZUG4>
.
You are receiving this because you authored the thread.Message ID:
@.***>
pchickey commented on issue #10167:
What's going on here is that the Wasm VM does not have a way to unwind the stack when a function like libc's
exit
is called, so we have to implement it by having the WASI implementation throw a trap. In the C API, you can usewasmtime_error_exit_status
to check if the returned error is caused by a WASI exit, and you probably want to treat a WASI exit with code 0 the same as a successful call (the C API does not bake that assumption in for you).The Wasm Exception Handling proposal has recently progressed to Phase 4 and we want to implement it in wasmtime soon. Once it is widely available in WASI runtimes, we can then change the behavior of the WASI libc to implement
exit
with stack unwinding, rather than calling a special function that traps and requires user interpretation in this way.
bjorn3 commented on issue #10167:
we can then change the behavior of the WASI libc to implement exit with stack unwinding
That would be unsound at least when the guest language is rust.
std::process::exit
is defined to immediately exit the process without unwinding and in the libc crateexit
is defined asextern "C"
rather thanextern "C-unwind"
and thus unwinding out of it is UB.
davecramer commented on issue #10167:
Well it's good to know that there's nothing I can do about it.
I'm kind of surprised that nobody else has found this? Seems like it isn't used very much
It's not out of the realm of possibility that I could write what I want in Rust, it's just much easier in C.
alexcrichton commented on issue #10167:
@davecramer did you see Pat's link to
wasmtime_error_exit_status
? Does that not work for you? (That's the solution to this issue, and adding such handling to the C/Rust API examples would be reasonable too I think)
davecramer commented on issue #10167:
@alexcrichton honestly, no. Just got back from FOSDEM, bit ragged at the moment.
davecramer closed issue #10167:
Test Case
With the following python
def talk(message): return "Talk " + message def main(): print(talk("Hello World")) return 0 if __name__ == "__main__": main()
compiled to wasm using py2wasm
int main() { // Set up our context wasm_engine_t *engine = wasm_engine_new(); assert(engine != NULL); wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL); assert(store != NULL); wasmtime_context_t *context = wasmtime_store_context(store); // Create a linker with WASI functions defined wasmtime_linker_t *linker = wasmtime_linker_new(engine); wasmtime_error_t *error = wasmtime_linker_define_wasi(linker); if (error != NULL) exit_with_error("failed to link wasi", error, NULL); wasm_byte_vec_t wasm; // Load our input file to parse it next FILE *file = fopen("wasm/test.wasm", "rb"); if (!file) { printf("> Error loading file!\n"); exit(1); } fseek(file, 0L, SEEK_END); size_t file_size = ftell(file); wasm_byte_vec_new_uninitialized(&wasm, file_size); fseek(file, 0L, SEEK_SET); if (fread(wasm.data, file_size, 1, file) != 1) { printf("> Error loading module!\n"); exit(1); } fclose(file); // Compile our modules wasmtime_module_t *module = NULL; error = wasmtime_module_new(engine, (uint8_t *)wasm.data, wasm.size, &module); if (!module) exit_with_error("failed to compile module", error, NULL); wasm_byte_vec_delete(&wasm); // Instantiate wasi wasi_config_t *wasi_config = wasi_config_new(); assert(wasi_config); wasi_config_inherit_argv(wasi_config); wasi_config_inherit_env(wasi_config); wasi_config_inherit_stdin(wasi_config); wasi_config_inherit_stdout(wasi_config); wasi_config_inherit_stderr(wasi_config); wasm_trap_t *trap = NULL; error = wasmtime_context_set_wasi(context, wasi_config); if (error != NULL) exit_with_error("failed to instantiate WASI", error, NULL); // Instantiate the module error = wasmtime_linker_module(linker, context, "", 0, module); if (error != NULL) exit_with_error("failed to instantiate module", error, NULL); // Run it. wasmtime_func_t func; error = wasmtime_linker_get_default(linker, context, "main", 0, &func); if (error != NULL) exit_with_error("failed to locate default export for module", error, NULL); error = wasmtime_func_call(context, &func, NULL, 0, NULL, 0, &trap); if (error != NULL || trap != NULL){ exit_with_error("error calling default export", error, trap); } // Clean up after ourselves at this point wasmtime_module_delete(module); wasmtime_store_delete(store); wasm_engine_delete(engine); return 0; } static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap) { fprintf(stderr, "error: %s\n", message); wasm_byte_vec_t error_message; if (error != NULL) { wasmtime_error_message(error, &error_message); wasmtime_error_delete(error); } else { wasm_trap_message(trap, &error_message); wasm_trap_delete(trap); } fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data); wasm_byte_vec_delete(&error_message); exit(1); }
TODO: upload Wasm file here
I get the errorTalk Hello World error: error calling default export error while executing at wasm backtrace: 0: 0x32a019 - <unknown>!__wasi_proc_exit 1: 0x3286df - <unknown>!_Exit 2: 0x33301f - <unknown>!exit 3: 0x16698d - <unknown>!Py_Exit 4: 0x34b2dc - <unknown>!main 5: 0x329c22 - <unknown>!__main_void 6: 0x5002 - <unknown>!_start note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information Caused by: Exited with i32 exit status 0
Versions and Environment
Wasmtime version or commit:
29.0.0Operating system: macos Sonoma 14.7.2
Architecture: ARM
davecramer commented on issue #10167:
@davecramer did you see Pat's link to
wasmtime_error_exit_status
? Does that not work for you? (That's the solution to this issue, and adding such handling to the C/Rust API examples would be reasonable too I think)That works fine.
Now on to how to pass data back and forth without using argc, argv.
Thanks!
Last updated: Feb 28 2025 at 02:27 UTC