Skip to content

Hold writes until the SYN-ACK has been sent - #106

Open
FrenchToblerone54 wants to merge 1 commit into
narrowlink:mainfrom
FrenchToblerone54:tcp-write-before-synack
Open

FrenchToblerone54 wants to merge 1 commit into
narrowlink:mainfrom
FrenchToblerone54:tcp-write-before-synack

Conversation

@FrenchToblerone54

Copy link
Copy Markdown

Problem

The SYN-ACK is sent by the session's task, which may not have run when the caller gets the stream. A write made in that window goes out through poll_write under the initial sequence number, ahead of the SYN-ACK. The peer does not accept data before the handshake, so the connection stalls or is reset. It is more likely on a current-thread runtime, or when the accepting task writes right after accept() returns.

Reproduce

Create a stream from a SYN and call poll_write before yielding to the runtime. The write is accepted and its packet reaches the device before the SYN-ACK. The new test checks the order of the packets.

Fix

  • poll_write registers its waker on write_notify and returns Pending while the session is still in Listen.
  • The task wakes write_notify right after it has sent the SYN-ACK and moved to SynReceived.

Once the SYN-ACK is out, writes behave as before.

Test

write_before_the_syn_ack_waits_for_it in src/stream/tcp.rs. It fails without the change ("a write was accepted before the SYN-ACK went out") and passes with it; it also checks that the writer is woken and that the data follows the SYN-ACK. cargo test and cargo clippy --all-targets are clean.

A write made before the task that answers the SYN has run was sent under the
initial sequence number, ahead of the SYN-ACK, which the peer does not accept.
Keep poll_write pending while the session is still in Listen and wake it once
the SYN-ACK is on its way.
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.

1 participant