• Brad Fitzpatrick's avatar
    net/http: tighten protocol between Transport.roundTrip and persistConn.readLoop · 7fa98467
    Brad Fitzpatrick authored
    In debugging the flaky test in #13825, I discovered that my previous
    change to tighten and simplify the communication protocol between
    Transport.roundTrip and persistConn.readLoop in
    https://golang.org/cl/17890 wasn't complete.
    
    This change simplifies it further: the buffered-vs-unbuffered
    complexity goes away, and we no longer need to re-try channel reads in
    the select case. It was trying to prioritize channels in the case that
    two were readable in the select. (it was only failing in the race builder
    because the race builds randomize select scheduling)
    
    The problem was that in the bodyless response case we had to return
    the idle connection before replying to roundTrip. But putIdleConn
    previously both added it to the free list (which we wanted), but also
    closed the connection, which made the caller goroutine
    (Transport.roundTrip) have two readable cases: pc.closech, and the
    response. We guarded against similar conditions in the caller's select
    for two readable channels, but such a fix wasn't possible here, and would
    be overly complicated.
    
    Instead, switch to unbuffered channels. The unbuffered channels were only
    to prevent goroutine leaks, so address that differently: add a "callerGone"
    channel closed by the caller on exit, and select on that during any unbuffered
    sends.
    
    As part of the fix, split putIdleConn into two halves: a part that
    just returns to the freelist, and a part that also closes. Update the
    four callers to the variants each wanted.
    
    Incidentally, the connections were closing on return to the pool due
    to MaxIdleConnsPerHost (somewhat related: #13801), but this bug
    could've manifested for plenty of other reasons.
    
    Fixes #13825
    
    Change-Id: I6fa7136e2c52909d57a22ea4b74d0155fdf0e6fa
    Reviewed-on: https://go-review.googlesource.com/18282
    Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: 's avatarAndrew Gerrand <adg@golang.org>
    7fa98467
Name
Last commit
Last update
..
cgi Loading commit data...
cookiejar Loading commit data...
fcgi Loading commit data...
httptest Loading commit data...
httputil Loading commit data...
internal Loading commit data...
pprof Loading commit data...
testdata Loading commit data...
client.go Loading commit data...
client_test.go Loading commit data...
clientserver_test.go Loading commit data...
cookie.go Loading commit data...
cookie_test.go Loading commit data...
doc.go Loading commit data...
example_test.go Loading commit data...
export_test.go Loading commit data...
filetransport.go Loading commit data...
filetransport_test.go Loading commit data...
fs.go Loading commit data...
fs_test.go Loading commit data...
h2_bundle.go Loading commit data...
header.go Loading commit data...
header_test.go Loading commit data...
http_test.go Loading commit data...
jar.go Loading commit data...
lex.go Loading commit data...
lex_test.go Loading commit data...
main_test.go Loading commit data...
method.go Loading commit data...
npn_test.go Loading commit data...
proxy_test.go Loading commit data...
race.go Loading commit data...
range_test.go Loading commit data...
readrequest_test.go Loading commit data...
request.go Loading commit data...
request_test.go Loading commit data...
requestwrite_test.go Loading commit data...
response.go Loading commit data...
response_test.go Loading commit data...
responsewrite_test.go Loading commit data...
serve_test.go Loading commit data...
server.go Loading commit data...
sniff.go Loading commit data...
sniff_test.go Loading commit data...
status.go Loading commit data...
transfer.go Loading commit data...
transfer_test.go Loading commit data...
transport.go Loading commit data...
transport_test.go Loading commit data...
triv.go Loading commit data...