diff --git a/sdk/tests/wasi.rs b/sdk/tests/wasi.rs index 251a3de..1b4d4da 100644 --- a/sdk/tests/wasi.rs +++ b/sdk/tests/wasi.rs @@ -267,7 +267,21 @@ fn protocol() { assert_eq!(provider.read()["params"]["name"], "draining"); line.clear(); assert_eq!(idle.read_line(&mut line).unwrap(), 0); - assert!(std::net::TcpStream::connect(&address).is_err()); + // drain() wakes independent accept/read cancellations. Idle EOF does not + // order listener destruction: TCP may still complete a handshake, but that + // connection must close without serving work. Do not retry the connect. + if let Ok(mut late) = std::net::TcpStream::connect(&address) { + eprintln!("TCP handshake raced listener cancellation; waiting for close"); + // Reuse the four-second socket bound used by idle/active above. + late.set_read_timeout(Some(std::time::Duration::from_secs(4))) + .unwrap(); + let closed = std::io::Read::read(&mut late, &mut [0]); + assert!( + matches!(closed, Ok(0)) + || matches!(&closed, Err(e) if e.kind() == std::io::ErrorKind::ConnectionReset), + "late connection survived drain: {closed:?}" + ); + } assert!(provider.child.try_wait().unwrap().is_none()); provider.answer(&inflight, json!({})); line.clear(); @@ -279,6 +293,7 @@ fn protocol() { assert!(provider.child.try_wait().unwrap().is_none()); provider.answer(&background, json!({})); provider.finishes(); + assert!(std::net::TcpStream::connect(&address).is_err()); assert!( !dir.join("stopped").exists(), "drain is not the EOF stop hook"