-
Notifications
You must be signed in to change notification settings - Fork 203
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
crt1-command.c: always call wasi_proc_exit for _REENTRANT #367
base: main
Are you sure you want to change the base?
Conversation
Note: a return from main() is an equivalent of exit(), which should terminate sibling threads.
// Call atexit functions, destructors, stdio cleanup, etc. | ||
__wasm_call_dtors(); | ||
|
||
#ifdef _REENTRANT | ||
// `__wasi_proc_exit` terminates sibling threads. | ||
__wasi_proc_exit(r); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect the host runtime to take care of this, even we just return.. the host should terminate all threads from the outside, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't expect so because:
- at wasi level, nothing wrong with making the main thread returns while keeping other threads running.
- it's also consistent with what happens when other thread (
wasi_thread_start
) returns. - it's simpler to have less special-casing for main thread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If "exit and keep threads running" is something that we would want at the wasi level why wouldn't we also want it at the libc level? Can we agree on what they both want and just return from main here?
Another way of putting it, assuming returning from main without __wasi_proc_exit
is a useful thing to do, do we not want to allow wasi-libc users to do it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. Also, in the future when we migrate off of instance-per-thread, threads running after main returns is potentially awkward, because a main function could be called by a caller that isn't expecting the instance to keep running after main returns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, threads running after main thread exits is actually quite normal as far as i know.
such applications achieve that by calling pthread_exit, though.
as far as C is our concern, maybe there is not much differences between either approaches.
however, IMO, there is little point to make the main thread special in this regard.
I agree. Also, in the future when we migrate off of instance-per-thread, threads running after main returns is potentially awkward, because a main function could be called by a caller that isn't expecting the instance to keep running after main returns.
it's normal for unix waitpid etc to wait for all threads exit, not only the main thread.
i guess embedder apis should follow the semantics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__wasi_proc_exit
is implemented like a trap, with a stack unwind in some runtimes, and for small short-lived instances this is sometimes noticeable in performance. Letting_start
return to its outside-world caller is faster.
That seems like an implementation choice isn't it? There isn't anything about proc_exit that requires a trace is there? Also this is something that happens exactly once per instance.. are you sure it makes a measurable difference to real programs? ...also if there is a cost is seems odd to make only non-zero returning programs pay that cost. If true, that kind of sounds like an argument for a __wasi_set_exit_code
API ..
On Linux, there is no caller for
_start
to return to, so calling the_exit
function is required for exiting the process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__wasi_proc_exit
is implemented like a trap, with a stack unwind in some runtimes, and for small short-lived instances this is sometimes noticeable in performance. Letting_start
return to its outside-world caller is faster.That seems like an implementation choice isn't it? There isn't anything about proc_exit that requires a trace is there? Also this is something that happens exactly once per instance.. are you sure it makes a measurable difference to real programs? ...also if there is a cost is seems odd to make only non-zero returning programs pay that cost. If true, that kind of sounds like an argument for a
__wasi_set_exit_code
API ..
Actually a better solution might be to have _start return the exit code .. then we could simply delete this call.
On Linux, there is no caller for
_start
to return to, so calling the_exit
function is required for exiting the process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__wasi_proc_exit
is implemented like a trap, with a stack unwind in some runtimes, and for small short-lived instances this is sometimes noticeable in performance. Letting_start
return to its outside-world caller is faster.That seems like an implementation choice isn't it? There isn't anything about proc_exit that requires a trace is there? Also this is something that happens exactly once per instance.. are you sure it makes a measurable difference to real programs? ...also if there is a cost is seems odd to make only non-zero returning programs pay that cost. If true, that kind of sounds like an argument for a
__wasi_set_exit_code
API ..
_start
returning is just a normal function return operation. But proc_exit
is an unwind stack frames operation, which in some settings involves a fair amount of work. Wasm instances don't require starting up new OS processes; they can be very cheap.
Actually a better solution might be to have _start return the exit code .. then we could simply delete this call.
Yes, returning a value would have been a better way to do it. In the preview2 work we've already moved to having main
have a return value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__wasi_proc_exit
is implemented like a trap, with a stack unwind in some runtimes, and for small short-lived instances this is sometimes noticeable in performance. Letting_start
return to its outside-world caller is faster.That seems like an implementation choice isn't it? There isn't anything about proc_exit that requires a trace is there? Also this is something that happens exactly once per instance.. are you sure it makes a measurable difference to real programs? ...also if there is a cost is seems odd to make only non-zero returning programs pay that cost. If true, that kind of sounds like an argument for a
__wasi_set_exit_code
API ..
_start
returning is just a normal function return operation. Butproc_exit
is an unwind stack frames operation, which in some settings involves a fair amount of work. Wasm instances don't require starting up new OS processes; they can be very cheap.
do you have a specific implementation in your mind?
for that implementation, rewinding a single small function (_start
) is so heavy?
if so, i suppose it's a problem of that specific implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The size of the function doesn't change anything. In implementations where proc_exit
calls _Unwind_Resume
it sometimes has to do a fair amount of work. You're right that that's a cost of such implementations. And we are working on moving to return values which will obviate this whole situation. So the question here is what we want the behavior of proc_exit
and wasi_thread_exit
to be; see my comment below.
To summarize my thinking based on this discussion:
|
i still think returning from |
Note: for some reasons, the current logic in wasi-libc crt returns without wasi_proc_exit when the exit code is 0. maybe just to save a host call? cf. WebAssembly/wasi-libc#367
But wouldn't that make it hard to port existing programs that assume posix semantics (returning from If we are looking for way to achieve "exit while keeping background threads alive" why would we choose "return from start function" to implicitly mean that? Especially when existing program already assume that not to be true? Why not be explicit about that with a new API or an argument to new argument to the existing wasi_proc_exit? I think this is another reason we need to add |
C programs don't care about "returning from _start".
i feel the opposite. actually, "terminate other threads" is a new concept which wasi-threads is going to introduce. why not be explicit about that? |
If I understand correctly, one of the motivations for this is so that if we say that exiting from However, elsewhere, other people have been contemplating replacing Both of these would eliminate an API function and simplify the system. But we can't easily do both. What should we do? |
Ah, I think I see now. This PR mean that In that case, I withdraw my previous objection. |
who is "other people" and where is it?
theoretically we can do the both if we want as a wasm function can return multiple return values. |
I don't have links handy, but I think the motivation is straightforward:
Are you suggesting having a return value that tells the caller of |
ok. the most of motivation (except Typed main one) seems to apply to the "terminate other threads" part of i'm not sure how the "Typed Main non-i32 return value" part can work when a non-main thread does
sort of. |
necessary for the current wasi-libc. cf. WebAssembly/wasi-libc#367
Let's figure this out in the "thread exit" issue (WebAssembly/wasi-threads#7) and then come back to this. |
Note: a return from main() is an equivalent of exit(), which should terminate sibling threads.