Stream: wasi

Topic: What happens to in-progress background writes on drop?


view this post on Zulip Dave Bakker (badeend) (Jan 08 2024 at 21:32):

(Probably @Pat Hickey): While discussing #7749 I stumbled on a tricky situation; What should happen when a background write is still in progress and the socket is either shutdown or dropped entirely?
Regular POSIX/BSD sockets ensure that any previous send that was accepted by the kernel will get sent out, even after the socket has been closed. Or at least: the kernel will try its best. I.e. the following is valid code:

int client_fd = accept(listener_fd);
send(client_fd, "A big message", MSG_DONTWAIT);
// Not waiting here
close(client_fd);

The current libc implementation only calls check-write and write.

On blocking sockets we can add a blocking-flush at the end of every send in libc to make sure the send made it all the way to the kernel. I don't see a problem here.
On non-blocking sockets we could call flush but that wouldn't solve anything; if the final write was moved to a background task, it would still get lost without warning.

Thoughts?

Make tcp-socket::shutdown close the input/output-streams. This was already specified in the WITs, but not implemented nor enforced by any tests.

view this post on Zulip Pat Hickey (Jan 08 2024 at 21:50):

ah, yeah, i see what the problem is there

view this post on Zulip Pat Hickey (Jan 08 2024 at 21:50):

unfortunately there is just no such thing as a non-blocking "flush and close"

view this post on Zulip Pat Hickey (Jan 08 2024 at 21:51):

so im not sure what we can do there to make libc have a correct implementation of close() for non-blocking sockets that truly does flush

view this post on Zulip Pat Hickey (Jan 08 2024 at 21:59):

so yes, in conclusion, you are correct: when a libc socket is blocking, you'll need to do a blocking-flush after every output-stream.write to that socket in order to be correct. when a libc socket is nonblocking, we have a design problem which we cant resolve right now.

view this post on Zulip Dave Bakker (badeend) (Jan 08 2024 at 22:07):

The options as far as I can see:

  1. Do nothing :)
  2. Modify libc's close to call blocking-flush on the associated output-stream. Upside: no data is lost. Downside: close now becomes a potentially blocking operation.
  3. Modify the host implementation to keep the background write running even after the stream has been dropped. This is the only way to truly keep the POSIX semantics, but I doubt this is what was in mind while designing the streams interface.
  4. (others?)

view this post on Zulip Pat Hickey (Jan 08 2024 at 22:33):

yeah, i guess a big question is how many applications will have problems if we pick 2

view this post on Zulip Pat Hickey (Jan 08 2024 at 22:33):

we tried pretty hard to avoid 3, but maybe we have to do that

view this post on Zulip Pat Hickey (Jan 08 2024 at 22:40):

i assume we would break a significant amount of applications by doing nothing, because theyd mysteriously lose writes

view this post on Zulip Pat Hickey (Jan 08 2024 at 22:41):

i guess putting myself in the shoes of an application writer id be much more displeased about 1 than 2


Last updated: Dec 23 2024 at 12:05 UTC