Skip to content

Comments

wasip2: Deduplicate stream code in read/write/TCP#735

Open
alexcrichton wants to merge 1 commit intoWebAssembly:mainfrom
alexcrichton:refactor-read-and-write
Open

wasip2: Deduplicate stream code in read/write/TCP#735
alexcrichton wants to merge 1 commit intoWebAssembly:mainfrom
alexcrichton:refactor-read-and-write

Conversation

@alexcrichton
Copy link
Collaborator

This commit extends the support in #734 by deduplicating the separate paths for reading a stream shared between read and recvfrom, for example. The get_{read,write}_stream methods now return more metadata and the TCP recvfrom implementation delegates to an internal __wasilibc_read to perform the actual read. This opens up the door to supporting nonblocking reads/writes on other streams in the future, for example.

Comment on lines -35 to -43
if (entry->vtable->recvfrom != NULL)
return entry->vtable->recvfrom(entry->data, buf, nbyte, 0, NULL, NULL);

bool ok = false;

// Translate the file descriptor to an internal handle
streams_borrow_input_stream_t input_stream;
off_t *off;
if (__wasilibc_read_stream(fildes, &input_stream, &off, NULL) < 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously read would use recvfrom, if present in the vtable - that does not seem to be the case anymore - isn't this a breaking change for wasi-libc users?

From the limited research I've done, it seems that read and write are expected to behave just as recv and send on connected sockets:

The only difference between recv() and read(2) is the presence of
flags. With a zero flags argument, recv() is generally equivalent
to read(2) (but see NOTES).

https://www.man7.org/linux/man-pages/man2/recv.2.html

The send() call may be used only when the socket is in a connected
state (so that the intended recipient is known). The only
difference between send() and write(2) is the presence of flags.
With a zero flags argument, send() is equivalent to write(2).

https://www.man7.org/linux/man-pages/man2/send.2.html

Shouldn't the UDP implementation set the get_read_stream accordingly in the vtable here

static descriptor_vtable_t udp_vtable = {
.free = udp_free,
.set_blocking = udp_set_blocking,
.fstat = udp_fstat,
.bind = udp_bind,
.connect = udp_connect,
.getsockname = udp_getsockname,
.getpeername = udp_getpeername,
.recvfrom = udp_recvfrom,
.sendto = udp_sendto,
.getsockopt = udp_getsockopt,
.setsockopt = udp_setsockopt,
.poll_register = udp_poll_register,
.fcntl_getfl = udp_fcntl_getfl,
.fcntl_setfl = udp_fcntl_setfl,
};
to avoid UDP read regression?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added pretty recently in #734 so not a breaking change in that sense (hasn't shipped anywhere). That's true though that it would mean that read/write wouldn't work on UDP. Unfortunately this can't implement get_{read,write}_stream for UDP sockets beacuse they have a different primitive under the hood.

Do you know whether native libc/linux supports read or write on UDP sockets? I would have assumed not but I could very well be wrong...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using read & write is perfectly fine on a connected UDP socket and are equivalent to recv & send without flags

if (!entry)
return -1;
if (entry->vtable->sendto != NULL)
return entry->vtable->sendto(entry->data, buf, nbyte, 0, NULL, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like above, looks like UDP implementation should set get_write_stream to avoid regression here?

This commit extends the support in WebAssembly#734 by deduplicating the separate
paths for reading a stream shared between `read` and `recvfrom`, for
example. The `get_{read,write}_stream` methods now return more metadata
and the TCP `recvfrom` implementation delegates to an internal
`__wasilibc_read` to perform the actual read. This opens up the door to
supporting nonblocking reads/writes on other streams in the future, for
example.
@alexcrichton alexcrichton force-pushed the refactor-read-and-write branch from 7e001b7 to 3aed548 Compare February 20, 2026 20:55
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.

3 participants