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

Treat all FDs as "nonblocking" on wasm32 #234

Closed
TerrorJack opened this issue Dec 14, 2023 · 8 comments
Closed

Treat all FDs as "nonblocking" on wasm32 #234

TerrorJack opened this issue Dec 14, 2023 · 8 comments
Labels
approved Approved by CLC vote

Comments

@TerrorJack
Copy link

Hi CLC members! Based on my recent work in the ghc wasm backend, I would like to make a wasm-specific proposal. The high level tl;dr is simple: on wasm32, treat all FDs as "nonblocking" unconditionally, therefore always performing the underlying read/write operation directly while avoiding the usage of poll() to actually wait for the FD's readiness. This makes I/O much more robust on wasm32, especially in browsers, where there's no satisfactory implementation of the poll_oneoff wasi syscall.

This has already been implemented in https://gitlab.haskell.org/ghc/ghc/-/merge_requests/11697. The patch only affects the wasm32 platform and doesn't touch any other platforms, while fixing a few test cases previously marked as fragile on wasm32. The merge request contains more detailed explanations, so I'd like to use that as the source of truth for the time being, but feel free to ask any questions or require more clarifications here :)

@Bodigrim
Copy link
Collaborator

The only change in question is in cbits/InputReady.c, not even in Haskell parts of base, and indeed guarded by #if defined(wasm32_HOST_ARCH). I trust @TerrorJack to know what is best for WASM backend; unless there are other opinions, I'll trigger a vote soon.

@Bodigrim
Copy link
Collaborator

Dear CLC members, let's vote on the proposal to change fdReady in cbits/InputReady to be const True under WASM backend. See https://gitlab.haskell.org/ghc/ghc/-/merge_requests/11697/diffs for details and tests.

@mixphix @hasufell @velveteer @angerman @parsonsmatt @tomjaguarpaw


+1 from me. The change fixes several tests, which were marked as fragile before.

@hasufell
Copy link
Member

+1

1 similar comment
@velveteer
Copy link
Contributor

+1

@tomjaguarpaw
Copy link
Member

+1


I agree with @Bodigrim's assessment here: #234 (comment)

@Ericson2314
Copy link
Contributor

Is there some upstream discussion of poll_oneoff not working well? I would be curious.

@angerman
Copy link

+1 on this.

@Bodigrim
Copy link
Collaborator

Thanks all, that's enough votes to approve.

@Bodigrim Bodigrim added the approved Approved by CLC vote label Jan 17, 2024
KDr2 pushed a commit to KDr2/ghc that referenced this issue Jan 18, 2024
On posix platforms, when performing read/write on FDs, we check the
nonblocking flag first. For FDs without this flag (e.g. stdout), we
call fdReady() first, which in turn calls poll() to wait for I/O to be
available on that FD. This is problematic for wasm32-wasi: although
select()/poll() is supported via the poll_oneoff() wasi syscall, that
syscall is rather heavyweight and runtime behavior differs in
different wasi implementations. The issue is even worse when targeting
browsers, given there's no satisfactory way to implement async I/O as
a synchronous syscall, so existing JS polyfills for wasi often give up
and simply return ENOSYS.

Before we have a proper I/O manager that avoids poll_oneoff() for
async I/O on wasm, this patch improves the status quo a lot by merely
pretending all FDs are "nonblocking". Read/write on FDs will directly
invoke read()/write(), which are much more reliably handled in
existing wasi implementations, especially those in browsers.

Fixes #23275 and the following test cases: T7773 isEOF001 openFile009
T4808 cgrun025

Approved by CLC proposal ghc#234:
haskell/core-libraries-committee#234
hubot pushed a commit to ghc/ghc that referenced this issue Feb 5, 2024
On posix platforms, when performing read/write on FDs, we check the
nonblocking flag first. For FDs without this flag (e.g. stdout), we
call fdReady() first, which in turn calls poll() to wait for I/O to be
available on that FD. This is problematic for wasm32-wasi: although
select()/poll() is supported via the poll_oneoff() wasi syscall, that
syscall is rather heavyweight and runtime behavior differs in
different wasi implementations. The issue is even worse when targeting
browsers, given there's no satisfactory way to implement async I/O as
a synchronous syscall, so existing JS polyfills for wasi often give up
and simply return ENOSYS.

Before we have a proper I/O manager that avoids poll_oneoff() for
async I/O on wasm, this patch improves the status quo a lot by merely
pretending all FDs are "nonblocking". Read/write on FDs will directly
invoke read()/write(), which are much more reliably handled in
existing wasi implementations, especially those in browsers.

Fixes #23275 and the following test cases: T7773 isEOF001 openFile009
T4808 cgrun025

Approved by CLC proposal #234:
haskell/core-libraries-committee#234
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Approved by CLC vote
Projects
None yet
Development

No branches or pull requests

7 participants