@@ -175,7 +175,10 @@ mod sse_flush_repro {
175175
176176 struct WriterState {
177177 written : Vec < u8 > ,
178- /// If true, flush panics: that is smoltcp waiting for a TCP ACK.
178+ /// If true, `flush` never completes -- what tokio-smoltcp does while it
179+ /// waits for the peer to ACK the tx buffer. Kernel `TcpStream` and iroh
180+ /// `SendStream` both treat flush as a no-op, so the TUN path is the only
181+ /// one where this is real.
179182 flush_blocks : bool ,
180183 }
181184
@@ -211,7 +214,9 @@ mod sse_flush_repro {
211214
212215 fn poll_flush ( self : Pin < & mut Self > , _cx : & mut Context < ' _ > ) -> Poll < std:: io:: Result < ( ) > > {
213216 if self . state . lock ( ) . unwrap ( ) . flush_blocks {
214- panic ! ( "copy_flush must not flush; smoltcp flush waits for a TCP ACK" ) ;
217+ // No waker is registered, so this never resolves. An ACK that
218+ // does not come is exactly the case being guarded against.
219+ return Poll :: Pending ;
215220 }
216221 Poll :: Ready ( Ok ( ( ) ) )
217222 }
@@ -221,8 +226,13 @@ mod sse_flush_repro {
221226 }
222227 }
223228
224- /// Regression: smoltcp flush waits for ACK. This loop must still enqueue
225- /// the SSE terminator without that ACK, or EventSource never fires.
229+ /// Forwarding must not stall on a flush. Measured on a real TUN hop, a
230+ /// flush per chunk turned this loop into stop-and-wait: a 64 KiB write went
231+ /// from ~64ms to ~450ms, because every chunk waited for the previous ACK.
232+ /// The writer here refuses to complete a flush, so any implementation that
233+ /// depends on one finishing hits the timeout. What is asserted is the
234+ /// property -- both halves of the event get through -- not the absence of a
235+ /// particular call.
226236 #[ tokio:: test]
227237 async fn copy_flush_writes_sse_terminator_without_waiting_for_ack ( ) {
228238 let writer = ProbeWriter :: new ( true ) ;
0 commit comments