-
Notifications
You must be signed in to change notification settings - Fork 742
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
fix(wasi): don't fail select() on empty subscriptions #1580
Conversation
return `Ok(())` rather than `Err(EINVAL)` Signed-off-by: Harald Hoyer <harald@profian.com>
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'm not sure about this one...
I think we'll want to match other OSes, which would wait "forever" (no timeout), when hitting this case. I'm mostly concerned about two cases:
- Users that expect polling an empty poll to sleep/poll forever until, e.g., a process signal wakes them.
- Users calling poll in a loop.
The case would be broken, as we won't sleep forever, and for the second case we'll create an infinite loop.
Well, there are no other sources which could interrupt this call... no signals, no other threads. |
I think that's only currently the case. I think wasm/wasi could be expanded to support both signals and/or threads (in some fashion). |
so what? change the wasi poll? loop forever in mio? leave the error as is? |
Good question(s), don't have a good answer without some more information. For now, I think our best bed it not doing anything in Mio, i.e. return the error by the OS (well, WASI runtime). Next, we'll have to find the related use cases where this branch could be hit. Than we'll compare what happens on other platforms and see if we can get a single uniform (and desired) behaviour. |
@Thomasdezeeuw It is impossible to "match other OSes." POSIX states the following for
In contrast, Further, @sunfishcode Do you have any suggestions here? |
@Thomasdezeeuw please note that even if wasm gains threads, the "wait forever" behavior still never makes sense because wasm does not have, and will not gain, support for signals. So I suspect that "return immediately" is the only logical behavior. |
I can also add that it seems very unlikely that Wasm or WASI will ever add Unix-style asynchronous signals or thread cancellation, because they'd create many problems for JITs, and they'd interact in complex ways with host code called by Wasm code.
The public API that calls this code seems to be WASI's documentation could be more clear here, but the current intent is that So my question is, who is calling |
I do want to highlight one other perspective. It's not a priori clear to me that WASI should prevent or detect all "useless" behavior by its clients at the API level. Doing so may have a cost in either the ergonomics or the performance of the API for non-"useless" cases. By analogy, deadlocking is useless, and yet typical mutex APIs do prevent deadlock by their construction. But they may provide other tools or diagnostics to detect it. And so I second sunfishcode's question: why call Poll::poll(on nothing)? If we knew that, I think it'd be easier to answer whether that particular call site of WASI poll should bear the costs of checking for no events, or whether WASI poll should detect that case itself. |
@sunfishcode @kulakowski-wasm
@kulakowski-wasm So, I think we have three choices:
|
I've opened #1585 to document the situation until we can make a decision on this. |
If calling In my opinion this should be an open issue for discussion. |
It's not necessarily a bug though, if you have a process that support signals is valid to wait for a process signal using
This is a bit of a straw man argument as this doesn't depend on Mio at all but rather on the implementation. For example, it should be fairly easy to determine the number of process/tasks/
It wasn't broken, WASI is just a different environment to the one Mio is usually run in (i.e. an OS process).
That's what we're doing right here... discussing this issue. |
I wasn't aware that this use case included signals as a halting mechanism. In that case, I feel it's perfectly reasonable to "halt until signal on signal-supported platforms, or error out on ones that don't." |
@haraldh What prompted putting this patch in |
Well, I would have put it in tokio, but there is no book keeping of the number of subscribed interests to check for diff --git a/tokio/src/io/driver/mod.rs b/tokio/src/io/driver/mod.rs
index 7d8650a3..98bc14d6 100644
--- a/tokio/src/io/driver/mod.rs
+++ b/tokio/src/io/driver/mod.rs
@@ -168,6 +168,13 @@ impl Driver {
match self.poll.poll(&mut events, max_wait) {
Ok(_) => {}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+ #[cfg(target_os = "wasi")]
+ Err(e) if e.kind() == io::ErrorKind::InvalidInput => {
+ // FIXME: number of Interests != 0
+ if false {
+ return Err(e);
+ }
+ }
Err(e) => return Err(e),
} |
@haraldh I think we want to go up another level and understand why I expect we can change Wasmtime's poll_oneoff to meet your needs in this situation, but I want to understand what the application ultimately wants it to do. |
@sunfishcode that is a good question, which we can ask @Thomasdezeeuw :) |
Reading up on
From the
|
@Thomasdezeeuw wrote:
Well, it seems all the tokio tests in this patch are affected and call |
Ok, if the
and this one is missing in wasi, cause we disable the signal module in our PR. |
Or the |
so, this is the call trace: impl Park for Driver {
fn park(&mut self) -> io::Result<()> {
self.turn(None)?;
Ok(())
} and |
@haraldh I think this should be solved in Tokio. If the runtime doesn't have any processes to run, nor registered any I/O sources and can't be awoken by a process signal or another thread (like the case for WASM/WASI) then I think the runtime should return/shutdown as nothing else needs to/can be done. |
ok, will do a follow-up tokio PR |
return
Ok(())
rather thanErr(EINVAL)
Signed-off-by: Harald Hoyer harald@profian.com