-
Notifications
You must be signed in to change notification settings - Fork 37
Description
I am making a WASM-based language service running completely within VS Code powered by the WASM execution engine extension. During the porting process, I noticed some missing feature that kept my language server from establishing the connection properly. After much investigation, I pinpointed the concrete requirements in WASI Preview 1's I/O handling to enable proper cooperative I/O multiplexing in WebAssembly programs without resorting to the threads extension.
First of all, I admit my use case is niche. The language server of interest, Agda language server, is written in Haskell and can be compiled with the Glasgow Haskell Compiler (GHC). Its WASM backend (specifically its runtime, RTS) does not yet have thread support. Without a threaded RTS, the Haskell program can still operate concurrently, but given an average best-effort WASI implementation, it is likely unable to maintain a duplex communication with the client.
Specifically, I propose changes on VS Code's WASM execution engine to (1.) provide a nonblocking way to read stdin-pipes and (2.) implement the blocking behavior in poll_oneoff to better align with POSIX-like I/O expectations on multiplexing.
1. Non-blocking stdin reads
- Current behavior:
fd_read()on stdin blocks indefinitely when no input is available, leading to starvation. - Proposed behavior: Allow
fd_read()on stdin to returnEAGAIN(WasiError.again) when no input is available, enabling non-blocking operation. - Benefits: This change prevents runtime softlocks in cooperative schedulers, enables standard non-blocking I/O patterns, without affecting existing program expecting blocking behavior. I expect this to be a minor interface change.
2. Correct poll_oneoff blocking on stdin
- Current behavior:
poll_oneoffreturns immediately even when subscriptions expect blocking on stdin readiness. - Proposed behavior:
poll_oneoffshould block when subscriptions specify waiting for stdin to become readable and there is no clock event present, resembling the POSIXselect()semantics. - Benefits: This enables proper event-driven I/O multiplexing, fixes broken assumptions in runtimes that rely on blocking poll behavior, and improves WASI's fidelity to standard I/O models. This would be very complex compared to 1., but since my only concern is stdin, it is possible to apply enough hacks just for my use case.
References
Here is my study of non-blocking reads on various WASM runtimes. A PoC implementation can be found in the fork agda-web/vscode-wasm. I am available to provide more context and assist the shaping if needed.