@@ -408,7 +408,9 @@ pub fn Blocking(comptime H: type) type {
408408 // directly when integrating with an http server
409409 pub fn readLoop (self : * Self , hc : * HandlerConn (H )) ! void {
410410 defer self .cleanupConn (hc );
411- try posix .setsockopt (hc .socket , posix .SOL .SOCKET , posix .SO .RCVTIMEO , & Timeout .none );
411+ if (shouldClearReceiveTimeout (builtin .os .tag )) {
412+ try posix .setsockopt (hc .socket , posix .SOL .SOCKET , posix .SO .RCVTIMEO , & Timeout .none );
413+ }
412414
413415 // In BlockingMode, we always assign a reader for the duration of the connection
414416 // In scenarios where client rarely send data, this is going to use up an unecessary amount
@@ -1829,6 +1831,13 @@ fn socketWrite(socket: posix.socket_t, buf: []const u8) !usize {
18291831 return posix .write (socket , buf );
18301832}
18311833
1834+ fn shouldClearReceiveTimeout (os_tag : std.Target.Os.Tag ) bool {
1835+ // Regression: on Windows, resetting SO_RCVTIMEO to a zero timeval after the
1836+ // handshake can cause the next websocket read to fail immediately. Leave the
1837+ // handshake timeout in place there until the underlying socket behavior is fixed.
1838+ return os_tag != .windows ;
1839+ }
1840+
18321841fn timestamp () u32 {
18331842 if (comptime @hasDecl (posix , "CLOCK" ) == false or posix .CLOCK == void ) {
18341843 return @intCast (std .time .timestamp ());
@@ -1992,6 +2001,12 @@ test "Conn: close" {
19922001 }
19932002}
19942003
2004+ test "shouldClearReceiveTimeout skips Windows" {
2005+ try t .expectEqual (false , shouldClearReceiveTimeout (.windows ));
2006+ try t .expectEqual (true , shouldClearReceiveTimeout (.linux ));
2007+ try t .expectEqual (true , shouldClearReceiveTimeout (.macos ));
2008+ }
2009+
19952010fn testStream (handshake : bool ) ! net.Stream {
19962011 const timeout = std .mem .toBytes (std.posix.timeval { .sec = 0 , .usec = 20_000 });
19972012 const address = try std .net .Address .parseIp ("127.0.0.1" , 9292 );
0 commit comments