Skip to content

Avoid calling poll_oneoff with zero subscriptions.#162

Merged
sunfishcode merged 7 commits intomasterfrom
pause
Jun 2, 2020
Merged

Avoid calling poll_oneoff with zero subscriptions.#162
sunfishcode merged 7 commits intomasterfrom
pause

Conversation

@sunfishcode
Copy link
Copy Markdown
Member

With WebAssembly/WASI#193 merged, WASI is moving
to make poll_oneoff with no arguments an error. Even though that's in
ephemeral and not yet in a snapshot, we can start to anticipate it in
libc:

  • Remove the pause function, since WASI has no signals and thus no
    way to ever wake it up short of having the host terminate it.
  • Make poll and pselect return ENOTSUP in the case of having no
    events to wait for.

@marmistrz
Copy link
Copy Markdown

Wouldn't it be preferable to immediately return ENOTSUP without calling __wasi_poll_oneoff?

@sunfishcode
Copy link
Copy Markdown
Member Author

This path should be very rare, and when it does happen, it probably means that applications need to change their code anyway, because WASI lacks signal handlers which you'd need to make meaningful use of it.

@kubkon
Copy link
Copy Markdown
Contributor

kubkon commented Jan 18, 2020

Hmm, FWIW I agree with @marmistrz on this one. However, having said that, since this indeed should probe the dev to fix their app since we don't (and probably won't, right?) have signal handlers, I guess we're good to go here.

@kubkon
Copy link
Copy Markdown
Contributor

kubkon commented Jan 18, 2020

Oh, and FWIW, the title is slightly misleading as at first read it sounds as if subscriptions == vec![], then we won't actually call __wasi_poll_oneoff, whereas what we actually have here is that we still make the syscall but error out if nevents == 0.

@sunfishcode
Copy link
Copy Markdown
Member Author

Ah, that's actually an error. I've now added a patch to this PR to fix this, which also clarifies my intent here: we should return ENOTSUP when there are zero subscriptions, not zero events. The code was confusing before because nevents was reused. I've now split it so that nsubscriptions is separate from nevents.

Concerning whether we should check nsubscriptions == 0 before or after the poll_oneoff call, I see this as an optimization tradeoff. Putting it before makes the nsubscriptions == 0 case faster, while putting it after makes the nsubscriptions != 0 case slightly faster. Since we're interpreting the nsubscriptions == 0 case as an application error, optimizing it doesn't seem to matter.

@sunfishcode
Copy link
Copy Markdown
Member Author

@marmistrz Does this PR with the change to not conflate nevents and nsubscriptions make sense?

@marmistrz
Copy link
Copy Markdown

I'll share my feedback tomorrow.

@marmistrz
Copy link
Copy Markdown

There's one subtlety here that I'd like to see documented in a comment.

Should we return an error based on nfds or nsubscriptions? It's clear that nfds == 0 is currently invalid for wasi, but maybe there's a case when nfds > 0 but nsubscriptions == 0 (i.e. some of the events are invalid). We find out that the code is correct only after analyzing the code thoroughly.

We can see that if there's no timeout and nfds == 0, then we correctly return ENOTSUP.
On the other hand, if nfds > 0, then either (a) nsubscriptions is incremented at least once (b) created_events == false and we return ENOSYS. The comment says that it's temporary, though.

// POLLWRNORM are not specified. Disallow this for now.
if (!created_events) {
errno = ENOSYS;

We could also add an assertion that nsubscriptions > 0 if nfds > 0, but a comment why using nsubscriptions is correct is also fine.

@sunfishcode
Copy link
Copy Markdown
Member Author

I've now added comments explaining the nsubscriptions == 0. I assume the way to add support for pure POLLERR, POLLHUP and POLLNVAL will be to add new kinds of subscriptions, so the invariant will be maintained in that case.

@marmistrz
Copy link
Copy Markdown

The comment is unclear to me.

Note that nsubscriptions can be zero even when nfds is non-zero;

Such situation sounds like a bug to me, and it's impossible with current code.

if there are no pollfd entries with non-negative file descriptors, and no timeout, then there are no subscriptions which could wake up a poll.

Is this an explanation of the reason why we return ENOTSUP?

@marmistrz
Copy link
Copy Markdown

It's better now, but now it's not mentioned nor asserted that nfds > 0 implies nsubscriptions > 0

@marmistrz
Copy link
Copy Markdown

It's much better now. But shouldn't a situation when nsubscriptions == 0 with nfds > 0 rather be an EINVAL, if we accept such possibility in the future?

`ENOTSUP is

is missing a backtick :)

@sunfishcode
Copy link
Copy Markdown
Member Author

It's better now, but now it's not mentioned nor asserted that nfds > 0 implies nsubscriptions > 0

It doesn't; if an event's fd is negative, we don't create a subscription for it.

It's much better now. But shouldn't a situation when nsubscriptions == 0 with nfds > 0 rather be an EINVAL, if we accept such possibility in the future?

nsubscriptions == 0 with nfds > 0 would mean that the user gave us an array of subscriptions where all the fd fields are negative. In POSIX, that's a valid request, and would simply block indefinitely. But that's one of the cases we're saying WASI doesn't support here. So I think ENOTSUP is the right error.

`ENOTSUP is

is missing a backtick :)

Fixed!

With WebAssembly/WASI#193 merged, WASI is moving
to make `poll_oneoff` with no arguments an error. Even though that's in
ephemeral and not yet in a snapshot, we can start to anticipate it in
libc:
 - Remove the `pause` function, since WASI has no signals and thus no
   way to ever wake it up short of having the host terminate it.
 - Make `poll` and `pselect` return `ENOTSUP` in the case of having no
   events to wait for.
Make `poll` and `pselect` return `ENOTSUP` when asked to poll on zero
subscriptions, rather than when the systerm returns zero events.

While here, drop the `__wasilibc_unmodified_upstream` markers, which
were already pretty noisy here, and would be significantly worse with
this change.
@sunfishcode
Copy link
Copy Markdown
Member Author

Thanks!

@sunfishcode sunfishcode merged commit 5a7ba74 into master Jun 2, 2020
@sunfishcode sunfishcode deleted the pause branch June 1, 2023 00:16
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