-
Notifications
You must be signed in to change notification settings - Fork 95
Description
I had some discussion with @dicej today about some work in the WASI implementation of various implementations of streams. The main example here is tcp-socket.listen
which returns a stream<tcp-socket>
.
At the OS level Wasmtime is built on Tokio right now which provides this API for accepting sockets. Notably this does not provide a "readiness" style API and instead only provides an API of "do the accept right now and tell me the result".
This is somewhat at odds with a 0-length read of the the stream on the guest side where this is understood to semantically mean "please resolve this async read when the socket is ready to accept, but don't actually give me what's being accepted". In Wasmtime we can always perform an accept and buffer the result of the accept on the host, and that's what today's implementation does. My question and our discussion arose from this behavior, however, where I don't think this is necessarily what we want.
The main hazard of buffering a result is that if this were a shared resource of some kind (e.g. shared at the OS level, not the component model level) then buffering may not be what's desired here. For example if the same TCP listener on the host were loaned out to multiple wasm instances then buffering in one instance would prevent any other instance from accepting the socket. To make matters worse the guest which performed a 0-length read may then trap or close the listener altogether, permanently losing the buffered socket.
Basically the question I'd like to ask here is: can we relax the requirement about 0-length reads to be a "may block until ready" rather than "guaranteed to block until ready"? I'd like to update the Wasmtime implementation here to always say "0-length read? yep we're ready" and immediately return. That's a lie in the sense that it's not actually ready but it's the best we can do in Wasmtime without Tokio.
Now an important part here though is that we still actually implement this for other resources/streams. For example when reading a TCP socket we'd still handle the 0-length case specially and avoid actually reading any data, instead just waiting for readiness. My hope here is that we could enable these sorts of use cases when the stars align but at the same time not require every primitive everywhere to implement some sort of required buffering and handling of the buffered values.