Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle a return from wasi _start function correctly #2529

Merged
merged 2 commits into from
Sep 8, 2023

Conversation

yamt
Copy link
Collaborator

@yamt yamt commented Sep 4, 2023

this fixes a few test cases in wasi-threads testsuite like wasi_threads_return_main_block.

also, move the special handling for wasi proc exit to a more appropriate place.

this fixes a few test cases in wasi-threads testsuite
like wasi_threads_return_main_block.

also, move the special handling for wasi proc exit to
a more appropriate place.
@yamt yamt changed the title handle a return frow wasi _start function correctly handle a return from wasi _start function correctly Sep 4, 2023
@yamt
Copy link
Collaborator Author

yamt commented Sep 4, 2023

extracted from #2516

if (ret) {
wasm_runtime_set_exception(module_inst, wasi_proc_exit_exception);
/* exit_code is zero-initialized */
ret = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why need to set wasi_proc_exit_exception here? If ret is true, there should be no exception thrown and wasi_exit_code was already initialized as 0, seems we can do nothing?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to propagate it to other threads.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the main thread will wait until all other threads exit in wasm_exec_env_destroy, it doesn't meet the "wasi proc exit" exception, seems no need to propagate "wasi proc exit" for other threads to exit early? Or other threads may not finish their jobs normally, also other threads may fail to throw exception if they continue to run?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. a return from _start should behave as exit(0) because it's what wasi-libc expects.
  2. exit(0) should terminate other threads.

wasm_runtime_set_exception here is just a convenient way to terminate other threads.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I my concern is, suppose the sub thread is doing an important job, e.g. do some calculation, output important data to a file, can we terminate it from the main thread? Is it better to wait until the sub threads exit? In fact, there is API wasm_cluster_wait_for_all_except_self in thread manager.

Not sure whether there is reference about "a return from _start should behave as exit(0)" in wasi-libc?

@loganek What's your opinion?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not sure if i understand your concern.
the importance of the job is something apps should consider. not runtime.

Not sure whether there is reference about "a return from _start should behave as exit(0)" in wasi-libc?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not very sure whether it is a good behavior that the main thread terminates all others thread instead of waiting for them. But if you want to do that, can we just call the API wasm_cluster_terminate_all_except_self of thread manager:

#if WASM_ENABLE_THREAD_MGR != 0
    if (ret) {
        WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
        wasm_cluster_terminate_all_except_self(cluster, exec_env);
    }
#endif

It also sets the terminate flag for other threads.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i chose to use wasm_runtime_set_exception because:

  • what i want to do here is to mimic wasi proc_exit, which uses wasm_runtime_set_exception.
  • wasm_cluster_terminate_all_except_self seems unused (thus untested) and broken. (cluster->lock vs cluster_list_lock locking order issue.)
  • we don't need to join threads here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, if to use wasm_runtime_set_exception, could you please add comments to mention somewhat like we want to mimic wasi proc_exit and to terminate other threads? It is not very easy to understand the code :)
And could you wrap the code with #if WASM_ENABLE_THREAD_MGR != 0 .. #endif, it is only for multi-threading?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, if to use wasm_runtime_set_exception, could you please add comments to mention somewhat like we want to mimic wasi proc_exit and to terminate other threads? It is not very easy to understand the code :) And could you wrap the code with #if WASM_ENABLE_THREAD_MGR != 0 .. #endif, it is only for multi-threading?

i prefer less #ifdef in general. but ok. done.

}
return false;
if (new_argv != argv) {
wasm_runtime_free(new_argv);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clear_wasi_proc_exit_exception is only applied after calling wasi _start function now, is it a general handling of wasi? Will developer call other functions in wasi mode and then wasm_proc_exit occurs?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess it's a gray area.
proc_exit is supposed to terminate the "process".
the concept of "process" only makes sense in the context of a wasi command.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable, maybe we can apply the changes first, and modify if needed in the future.

}
/* report wasm proc exit as a success */
WASMModuleInstance *inst = (WASMModuleInstance *)module_inst;
if (!ret && strstr(inst->cur_exception, wasi_proc_exit_exception)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems both L117 and L115 make if in L121 always true.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's false if (ret == false and cur_exception == some other exception).

@@ -107,7 +107,22 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
the actual main function. Directly calling main function
may cause exception thrown. */
if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) {
return wasm_runtime_call_wasm(exec_env, func, 0, NULL);
const char *wasi_proc_exit_exception = "wasi proc exit";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it better if we use a global variable or macro to represent the string "wasi proc exit"? It is a very import constant string now。

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally we should stop using strings i guess.

also, make some code conditional on WASM_ENABLE_THREAD_MGR
@lum1n0us
Copy link
Collaborator

lum1n0us commented Sep 7, 2023

LGTM

Copy link
Contributor

@wenyongh wenyongh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@eloparco
Copy link
Contributor

eloparco commented Sep 7, 2023

I know we already had this conversation with @yamt, but with these changes, should we update trap_after_main_thread_finishes.c to have 0 as exit code and to replace the trap here with an assert? And even change the name of the tests and put some comments to describe the expected behavior. I could do it as a separate PR if it makes sense.

Or we drop the test completely since it has some overlapping with https://github.com/WebAssembly/wasi-threads/blob/main/test/testsuite/wasi_threads_exit_main_block.wat.

Because the test had another goal initially, to make sure the spawned threads kept running and its trap error code was propagated to the runtime. Now the implemented behavior is different instead. So I think we should update the test or drop it (it doesn't make much sense to me to keep it as it is).

@yamt
Copy link
Collaborator Author

yamt commented Sep 7, 2023

I know we already had this conversation with @yamt, but with these changes, should we update trap_after_main_thread_finishes.c to have 0 as exit code and to replace the trap here with an assert? And even change the name of the tests and put some comments to describe the expected behavior. I could do it as a separate PR if it makes sense.

i'm not sure if i understand what updates you are suggesting.
it already has 0 as exit code.
the trap and assert are not that different as they are both wasm unreachable.

Or we drop the test completely since it has some overlapping with https://github.com/WebAssembly/wasi-threads/blob/main/test/testsuite/wasi_threads_exit_main_block.wat.

it's also fine for me.

@wenyongh
Copy link
Contributor

wenyongh commented Sep 7, 2023

@eloparco I understand that the main thread already returns 0 and no need to change it. Changing buildin_trap to assert is that buildin_trap will throw exception in spawned thread, while assert (assume we use assert(true statement)) won't throw exception and the spawned thread exits normally.

I think it is a good case and had better not change it. A possible issue is that after main function returns and runtime set_exception("wasi proc exit") to the spawned thread, and then before the spawned thread handles the exception and terminate flag, it runs into the builtin_trap, throws unreachable exception and ends first. That means the main thread returns 0 while sub thread throws exception (and it may spread to the main thread then), not sure whether we should handle it? @yamt

@yamt
Copy link
Collaborator Author

yamt commented Sep 7, 2023

A possible issue is that after main function returns and runtime set_exception("wasi proc exit") to the spawned thread, and then before the spawned thread handles the exception and terminate flag, it runs into the builtin_trap, throws unreachable exception and ends first. That means the main thread returns 0 while sub thread throws exception (and it may spread to the main thread then), not sure whether we should handle it? @yamt

wrt racing multiple traps/exit, i plan to prevent wasm_runtime_set_exception from overwriting existing trap/exit. (not within this PR though)

@wenyongh
Copy link
Contributor

wenyongh commented Sep 8, 2023

A possible issue is that after main function returns and runtime set_exception("wasi proc exit") to the spawned thread, and then before the spawned thread handles the exception and terminate flag, it runs into the builtin_trap, throws unreachable exception and ends first. That means the main thread returns 0 while sub thread throws exception (and it may spread to the main thread then), not sure whether we should handle it? @yamt

wrt racing multiple traps/exit, i plan to prevent wasm_runtime_set_exception from overwriting existing trap/exit. (not within this PR though)

Got it, great, thanks!

@wenyongh wenyongh merged commit 534a8cf into bytecodealliance:main Sep 8, 2023
368 checks passed
yamt added a commit to yamt/wasm-micro-runtime that referenced this pull request Sep 20, 2023
On posix-like platforms, the rest of wasi-threads tests
should pass after the recent changes including the following PRs:

bytecodealliance#2516
bytecodealliance#2524
bytecodealliance#2529
yamt added a commit to yamt/wasm-micro-runtime that referenced this pull request Sep 21, 2023
On posix-like platforms, the rest of wasi-threads tests
should pass after the recent changes including the following PRs:

bytecodealliance#2516
bytecodealliance#2524
bytecodealliance#2529
yamt added a commit to yamt/wasm-micro-runtime that referenced this pull request Sep 22, 2023
On posix-like platforms, the rest of wasi-threads tests
should pass after the recent changes including the following PRs:

bytecodealliance#2516
bytecodealliance#2524
bytecodealliance#2529
yamt added a commit to yamt/wasm-micro-runtime that referenced this pull request Sep 23, 2023
On posix-like platforms, the rest of wasi-threads tests
should pass after the recent changes including the following PRs:

bytecodealliance#2516
bytecodealliance#2524
bytecodealliance#2529
wenyongh pushed a commit that referenced this pull request Sep 26, 2023
On posix-like platforms, the rest of wasi-threads tests
should pass after the recent changes including the following PRs:
#2516, #2524, #2529, #2571, #2576 and #2582.
victoryang00 pushed a commit to victoryang00/wamr-aot-gc-checkpoint-restore that referenced this pull request May 27, 2024
…#2529)

This fixes a few test cases in wasi-threads testsuite like wasi_threads_return_main_block.
And also move the special handling for "wasi proc exit" to a more appropriate place.
victoryang00 pushed a commit to victoryang00/wamr-aot-gc-checkpoint-restore that referenced this pull request May 27, 2024
On posix-like platforms, the rest of wasi-threads tests
should pass after the recent changes including the following PRs:
bytecodealliance#2516, bytecodealliance#2524, bytecodealliance#2529, bytecodealliance#2571, bytecodealliance#2576 and bytecodealliance#2582.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants