I would like to make some changes to the error handling code in wasmtime's wasi-sockets implementation. Mainly to simplify mapping back-and-forth between the BSD error codes. As part of this change I would also like to change some error codes defined in the wasi-sockets proposal (which I'm the champion of).
I've noticed with other WASI proposals, that sometimes changes are first made in the wasmtime repo with updates to both the implementation _and_ their copy of the spec (/crates/wasi/wit/...
) within the same PR. And then later the proposal repo is updated, retroactively.
With the changes I have in mind, this seems the most pragmatic approach because they're implementation driven.
Are there any guidelines on this practice for me to follow?
for a while we let the wit in wasmtime and the spec diverge pretty far, because we were in a "prototype" stage, but since we are now getting close to shipping p2, ive been trying to make a PR to wasmtime with local spec + implementation changes, and simultaneously make a PR to the spec repos upstream with whatever changes, and I leave links between the two issues
imo, specs that haven't yet had implementation-driven changes are not yet mature specs. its only by implementing and testing the specs, and iterating based on what we learn there, that specs become mature. so, be glad we are at this stage!
Alright, thanks! The past few days I've been working on a test suite for the TCP socket implementation, along with some associated tweaks to the implementation. I hope have a PR ready somewhere the coming week.
oh, wrt errors, i have mentioned this noodling to dan and others but i dont think to you
so, first off, we redesigned output-streams to have last-operation-failed
and closed
as distinct errors
i want to do the same thing to input-stream, especially this is informed by implementing http stuff
the other thing i want to do, after we switch over to resources, is to make last-operation-failed
have a payload stream-error-cause
resource
and that has a method describe() -> option<string>
that gives debug info, and the docs say you have to promise to not use that for control flow, just for displaying debug info, so that we dont get into the bad game of strings needing to be identical across engines/implementations
and then we can also have sockets be able to elaborate it into some more particular error
e.g. a resource tcp { elaborate(stream-error-cause) -> option<more-specific-error-enum> }
Good to know! The changes I have so far don't impact streams, but rather the methods on the socket resource themselves (bind, accept, listen, connect, etc...)
returning the option because its ok for the tcp to say "i dont know anything about that error" because perhaps it came from some other place
ok! good to know
i think for http we want this to be able to elaborate on what sort of protocol errors happened
we havent worked out all the details yet
it seems more useful when you have some sort of more complex protocol that is being used via a stream, vs files and sockets which are low level enough where theres really not many reasons a stream can go wrong
Just for my information, is this an inbetween solution until proper Preview3 stream
s are a thing?
i think so, yeah
the way i see preview3 streams right now is that theyre something we need one day, but we cant really design them until we see how the preview 2 streams end up getting used in implementations
so rather than anticipate what theyre going to look like, we're going to try to make preview 2 streams work as nicely as we can with all the things we need to implement right now, and then figure out the path to preview 3 when the time comes.
make sense
same basic attitude as i said above, that a spec is only mature as you iterate on it with the things that come up in implementation.
Can there be multiple last-operation-failed
s on a single stream without having to terminate the stream?
nope - we're defining streams that, once theres any failure, theyre closed forever
we havent found any cases where that didnt work
I have two :P
Instead of having an accept
method you'd need to continuously poll, I'd love to have a way to (somehow) have listen
return a stream of newly accepted client socket resources. The problem is that accept
can return transient errors like ECONNABORTED. This can be an indicator to the application that the listen queue is filling up. At the moment the spec dictates that these temporary error must be skipped over, precisely because of the envisioned fail-once/closed-forever semantics.
An other is UDP send&receive. Those are currently methods sending individual datagrams, but "ideally" I would like to have a stream of datagrams in the future
I understand that those use cases are not relevant at the moment, because we're only dealing with byte streams. But they might become relevant in the future?
Alternative for the accept
stream specifically could be to explicitly model errors as messages in the stream. Eg. listen() -> stream<variant { temp-error(code), new-client(sock-resource) }>
But I don't know if that alternative generalizes well for cases where the error may occur while writing/pushing items to a stream. (The UDP Send stream example)
ah, yes, i see what you mean now. i think as we generalize streams to arbitrary datatypes we'll be able to support what you describe
we definitely have places where that sort of semantics is required, e.g. readdir's pseudo-stream
but for bytestreams, we havent found that yet.
@Badeend With Preview 3's typed streams, we can have the stream element type be a result
, which would be a way to report accept
errors without having the stream as a whole fail.
The same applies to modelling UDP datagrams as streams.
Yeah, that's more or less what I thought too (above)
I'll change the implementation & spec to allow for these errors
Last updated: Nov 22 2024 at 16:03 UTC