Stream: git-wasmtime

Topic: wasmtime / issue #10167 error: error calling default export


view this post on Zulip Wasmtime GitHub notifications bot (Feb 02 2025 at 04:53):

davecramer added the bug label to Issue #10167.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 02 2025 at 04:53):

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 error

Talk 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.0

Operating system: macos Sonoma 14.7.2

Architecture: ARM

view this post on Zulip Wasmtime GitHub notifications bot (Feb 02 2025 at 04:54):

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 error

Talk 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.0

Operating system: macos Sonoma 14.7.2

Architecture: ARM

view this post on Zulip Wasmtime GitHub notifications bot (Feb 02 2025 at 10:18):

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.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 02 2025 at 10:18):

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.

https://github.com/bytecodealliance/wasmtime/blob/a0338af84f66cb452fdf4b692d4facb5d052c12d/src/commands/run.rs#L243-L249

view this post on Zulip Wasmtime GitHub notifications bot (Feb 02 2025 at 17:58):

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:
@.***>

view this post on Zulip Wasmtime GitHub notifications bot (Feb 02 2025 at 21:47):

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 use wasmtime_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.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 02 2025 at 21:53):

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 crate exit is defined as extern "C" rather than extern "C-unwind" and thus unwinding out of it is UB.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 03 2025 at 10:58):

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.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 03 2025 at 11:56):

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)

view this post on Zulip Wasmtime GitHub notifications bot (Feb 03 2025 at 12:52):

davecramer commented on issue #10167:

@alexcrichton honestly, no. Just got back from FOSDEM, bit ragged at the moment.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 03 2025 at 15:32):

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 error

Talk 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.0

Operating system: macos Sonoma 14.7.2

Architecture: ARM

view this post on Zulip Wasmtime GitHub notifications bot (Feb 03 2025 at 15:32):

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