Skip to content

Conversation

@yamt
Copy link
Contributor

@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 yamt force-pushed the wasi-start-return-as-exit branch from 9b77116 to 935f055 Compare September 4, 2023 10:48
@yamt
Copy link
Contributor 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
Collaborator

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
Contributor 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
Collaborator

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
Contributor 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
Collaborator

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
Contributor 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
Collaborator

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
Contributor 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
Collaborator

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
Contributor 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
Collaborator

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
Contributor 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
Collaborator

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
Contributor

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
Contributor 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).

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
Contributor

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
Contributor 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
Contributor

lum1n0us commented Sep 7, 2023

LGTM

Copy link
Collaborator

@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
Contributor 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
Collaborator

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
Contributor 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
Collaborator

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
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.
vickiegpt pushed a commit to vickiegpt/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.
vickiegpt pushed a commit to vickiegpt/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