Skip to content

Wait for Windows pipe writes to complete before reporting success - #101

Merged
floitsch merged 2 commits into
mainfrom
fix/windows-pipe-write-completion
Sep 14, 2026
Merged

floitsch merged 2 commits into
mainfrom
fix/windows-pipe-write-completion

Conversation

@floitsch

@floitsch floitsch commented Sep 13, 2026 •

Copy link
Copy Markdown
Member

Windows pipe writes currently return their queued byte count before WriteFile completes. A caller that writes and immediately closes can therefore discard the payload; the regression receives 0 of 262,144 bytes with the existing implementation.

Wait for pipe.write-result through ResourceState_ before returning the completed count. Serialize writers while a completion is outstanding, propagate asynchronous failures, and abort a writer when another task closes the pipe. Apply the same completion handling to each chunk of generic io.Data.

Depends on toitlang/toit#3221, which adds the completion primitive. package.yaml now requires ^2.0.0-alpha.199, targeting the next SDK release. Keep this PR in draft until that release includes the new primitive. Older SDK compilers do not recognize the new primitive.

Validation: cross-built the companion Windows SDK and ran all four new scenarios under Wine: byte-array delivery, chunked string-byte-slice delivery, broken-pipe failure, and concurrent close. The delivery regression fails against the original package. The existing pipe2_test could not run because this Wine environment has no cat executable.

@floitsch
floitsch marked this pull request as ready for review September 13, 2026 15:34
floitsch pushed a commit to toitlang/toit that referenced this pull request Sep 13, 2026
Closing Windows TCP sockets with an overlapped receive armed can reset
the peer and discard unread data. Closing TCP, UDP, pipe, and UART
handles also allows pending completions to write into freed `OVERLAPPED`
structures.

Add `WindowsOverlapped` to track successfully issued operations and
cancel/reap them before destroying their handles, events, and resources.
Synchronous failures are not waited on, because no operation was
started.

TCP writes now use nonblocking `send` and `FD_WRITE` readiness. Each
primitive call retries `send` directly; no cached write-readiness flag
can overwrite an `FD_WRITE` notification that arrives as a blocked send
returns. They report only bytes accepted by the transport, handle
partial writes and backpressure, and leave no queued `WSASend` for close
to cancel. This also corrects the address length passed to `connect` and
closes the auxiliary socket event. Waiting for a pending send inside the
shared event thread would stall unrelated I/O; nonblocking sends avoid
that dependency. See [Microsoft's send
semantics](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasend).

Add `pipe.write-result` to return the actual completed byte count, null
while pending, or an asynchronous error. The existing write primitive
retains its queued-count behavior for package compatibility.
[pkg-host#101](toitlang/pkg-host#101) uses the
new primitive to suspend the writing task until completion, serialize
concurrent writers, and propagate cancellation/errors. **Preventing pipe
write-then-close data loss requires that companion package update.** It
remains draft until an SDK release includes the new primitive and its
minimum SDK requirement can be updated.

UART writes and older host packages still report queued writes; closing
them may cancel pending data. The gzip test retains file input while the
SDK tests use the released host package.
@floitsch
floitsch force-pushed the fix/windows-pipe-write-completion branch from 19e5d07 to 1949a5c Compare September 14, 2026 15:27
@floitsch
floitsch merged commit b78cdac into main Sep 14, 2026
7 checks passed
@floitsch
floitsch deleted the fix/windows-pipe-write-completion branch September 14, 2026 15:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant