Skip to content

Commit 53d145a

Browse files
committed
fix: preventing hang when TCPSocket readable, but no app-data available
1 parent d7103a1 commit 53d145a

1 file changed

Lines changed: 33 additions & 4 deletions

File tree

lib/net/http.rb

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2495,10 +2495,17 @@ def begin_transport(req)
24952495
debug 'Conn close because of keep_alive_timeout'
24962496
@socket.close
24972497
connect
2498-
elsif @socket.io.to_io.wait_readable(0) && @socket.eof?
2499-
debug "Conn close because of EOF"
2500-
@socket.close
2501-
connect
2498+
elsif @socket.io.to_io.wait_readable(0)
2499+
# Check for EOF without blocking.
2500+
# With TLS 1.3, servers may send NewSessionTicket after responses,
2501+
# making the socket appear readable when only handshake data is
2502+
# pending. Using eof? here would block waiting for app data.
2503+
# See: https://bugs.ruby-lang.org/issues/19017
2504+
if eof_without_blocking?
2505+
debug "Conn close because of EOF"
2506+
@socket.close
2507+
connect
2508+
end
25022509
end
25032510
end
25042511

@@ -2527,6 +2534,28 @@ def end_transport(req, res)
25272534
end
25282535
end
25292536

2537+
# Non-blocking EOF check for TLS connections.
2538+
# Returns true if connection is at EOF, false otherwise.
2539+
# Unlike @socket.eof?, this won't block when TLS 1.3 NewSessionTicket
2540+
# messages are pending on the connection.
2541+
def eof_without_blocking?
2542+
result = @socket.io.read_nonblock(1, exception: false)
2543+
case result
2544+
when nil
2545+
# EOF - connection was closed
2546+
true
2547+
when :wait_readable, :wait_writable
2548+
# No data available yet, but connection is alive
2549+
false
2550+
when String
2551+
# Got actual data - push it back for later reads
2552+
@socket.io.ungetc(result)
2553+
false
2554+
end
2555+
rescue EOFError
2556+
true
2557+
end
2558+
25302559
def keep_alive?(req, res)
25312560
return false if req.connection_close?
25322561
if @curr_http_version <= '1.0'

0 commit comments

Comments
 (0)