Skip to content

net/http/httptrace: function called after RoundTrip returns an error #16957

Closed
@tombergan

Description

@tombergan

The documentation for httptrace says

// Functions may be
// called concurrently from different goroutines, starting after the
// call to Transport.RoundTrip and ending either when RoundTrip
// returns an error, or when the Response.Body is closed.

However, if RoundTrip is canceled or times out before t.dialConn completes, ConnectStart can be called concurrently with code that runs after RoundTrip returns an error.
https://golang.org/src/net/http/transport.go#L880

Here is a sample race found by TSAN:

WARNING: DATA RACE
Read at 0x00c420204418 by goroutine 98:
  [in my code that reads the final trace struct after RoundTrip has returned an error]

Previous write at 0x00c420204418 by goroutine 100:
  [in my implementation of ConnectStart]
  net.dialSingle()
      go/gc/src/net/dial.go:511 +0xde5
  net.dialSerial()
      go/gc/src/net/dial.go:489 +0x245
  net.(*Dialer).DialContext()
      go/gc/src/net/dial.go:371 +0x977
  [some frames redacted]
  net/http.(*Transport).dial()
      go/gc/src/net/http/transport.go:821 +0xe3
  net/http.(*Transport).dialConn()
      go/gc/src/net/http/transport.go:962 +0x242a
  net/http.(*Transport).getConn.func4()
      go/gc/src/net/http/transport.go:880 +0xa2

I'm not sure if this is a documentation bug or a code bug. The only way to implement the documentation faithfully is to either (a) prevent calling hooks after the conditions specified in the doc have been reached, or (b) wait for the background t.dialConn to complete before returning from RoundTrip with an error. The second solution doesn't seem practical. The first solution is doable, but do we really need a strict guarantee in the first place?

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions