Closed
Description
What version of Go are you using (go version
)?
$ go version go version go1.13.5 linux/amd64
Does this issue reproduce with the latest release?
1.13.5, yes
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/home/nuts/.cache/go-build" GOENV="/home/nuts/.config/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/home/nuts/golang-test/go-src" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/home/nuts/golang-test/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/home/nuts/golang-test/go/pkg/tool/linux_amd64" GCCGO="gccgo" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build701551313=/tmp/go-build -gno-record-gcc-switches"
What did you do?
Ran this code. although it uses elazarl/goproxy
package, behavour can be reproduced without this package.
package main
import (
"net/http"
"net/url"
"time"
"sync"
"io/ioutil"
"github.com/elazarl/goproxy"
"fmt"
)
func ProxyFunc(req *http.Request) (*url.URL, error) {
return url.Parse(req.RemoteAddr)
}
func prepareTransport() *http.Transport {
return &http.Transport{
Proxy: ProxyFunc,
//DisableKeepAlives: true,
ProxyConnectHeader: http.Header{
"User-Agent": { "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0" },
"Proxy-Connection": {"keep-alive"},
"Connection": {"keep-alive"},
},
}
}
func sendRequest(client *http.Client, proxy *url.URL, u *url.URL) {
for {
req := http.Request{
URL: u,
RemoteAddr: proxy.String(),
Method: "GET",
}
if res, err := client.Do(&req); err == nil {
defer res.Body.Close()
_, _ = ioutil.ReadAll(res.Body)
}
}
}
func spawnProxies(port string) {
proxy := goproxy.NewProxyHttpServer()
proxy.Verbose = false
fmt.Println(http.ListenAndServe(":" + port, proxy))
}
func main() {
numProxies := 4
client := http.Client{
Transport: prepareTransport(),
Timeout: time.Second * time.Duration(5),
}
u, _ := url.Parse("https://httpbin.org/")
proxyPorts := make([]string, 0, numProxies)
for i := 0; i < numProxies; i++ {
port := fmt.Sprint("800", i)
proxyPorts = append(proxyPorts, port)
go spawnProxies(port)
}
var wg sync.WaitGroup
wg.Add(numProxies)
for _, port := range proxyPorts {
proxy, _ := url.Parse("http://test:[email protected]:" + port)
go func() {
defer wg.Done()
sendRequest(&client, proxy, u)
}()
}
wg.Wait()
}
What did you expect to see?
Above code to run without data race warning.
What did you see instead?
==================
WARNING: DATA RACE
Write at 0x00c00008b530 by goroutine 22:
runtime.mapassign_faststr()
/home/nuts/golang-test/go/src/runtime/map_faststr.go:202 +0x0
net/http.(*Transport).dialConn()
/home/nuts/golang-test/go/src/net/textproto/header.go:22 +0x1d4f
net/http.(*Transport).dialConnFor()
/home/nuts/golang-test/go/src/net/http/transport.go:1308 +0x14f
Previous write at 0x00c00008b530 by goroutine 21:
runtime.mapassign_faststr()
/home/nuts/golang-test/go/src/runtime/map_faststr.go:202 +0x0
net/http.(*Transport).dialConn()
/home/nuts/golang-test/go/src/net/textproto/header.go:22 +0x1d4f
net/http.(*Transport).dialConnFor()
/home/nuts/golang-test/go/src/net/http/transport.go:1308 +0x14f
Goroutine 22 (running) created at:
net/http.(*Transport).queueForDial()
/home/nuts/golang-test/go/src/net/http/transport.go:1277 +0x68a
net/http.(*Transport).getConn()
/home/nuts/golang-test/go/src/net/http/transport.go:1231 +0x785
net/http.(*Transport).roundTrip()
/home/nuts/golang-test/go/src/net/http/transport.go:522 +0x83d
net/http.(*Transport).RoundTrip()
/home/nuts/golang-test/go/src/net/http/roundtrip.go:17 +0x42
net/http.send()
/home/nuts/golang-test/go/src/net/http/client.go:250 +0x6a8
net/http.(*Client).send()
/home/nuts/golang-test/go/src/net/http/client.go:174 +0x1ca
net/http.(*Client).do()
/home/nuts/golang-test/go/src/net/http/client.go:641 +0x2cc
main.sendRequest()
/home/nuts/golang-test/go/src/net/http/client.go:509 +0x11f
main.main.func1()
/home/nuts/golang-test/t.go:74 +0x80
Goroutine 21 (running) created at:
net/http.(*Transport).queueForDial()
/home/nuts/golang-test/go/src/net/http/transport.go:1277 +0x68a
net/http.(*Transport).getConn()
/home/nuts/golang-test/go/src/net/http/transport.go:1231 +0x785
net/http.(*Transport).roundTrip()
/home/nuts/golang-test/go/src/net/http/transport.go:522 +0x83d
net/http.(*Transport).RoundTrip()
/home/nuts/golang-test/go/src/net/http/roundtrip.go:17 +0x42
net/http.send()
/home/nuts/golang-test/go/src/net/http/client.go:250 +0x6a8
net/http.(*Client).send()
/home/nuts/golang-test/go/src/net/http/client.go:174 +0x1ca
net/http.(*Client).do()
/home/nuts/golang-test/go/src/net/http/client.go:641 +0x2cc
main.sendRequest()
/home/nuts/golang-test/go/src/net/http/client.go:509 +0x11f
main.main.func1()
/home/nuts/golang-test/t.go:74 +0x80
==================
==================
WARNING: DATA RACE
Write at 0x00c0000b84f0 by goroutine 22:
net/http.(*Transport).dialConn()
/home/nuts/golang-test/go/src/net/textproto/header.go:22 +0x1d67
net/http.(*Transport).dialConnFor()
/home/nuts/golang-test/go/src/net/http/transport.go:1308 +0x14f
Previous write at 0x00c0000b84f0 by goroutine 21:
net/http.(*Transport).dialConn()
/home/nuts/golang-test/go/src/net/textproto/header.go:22 +0x1d67
net/http.(*Transport).dialConnFor()
/home/nuts/golang-test/go/src/net/http/transport.go:1308 +0x14f
Goroutine 22 (running) created at:
net/http.(*Transport).queueForDial()
/home/nuts/golang-test/go/src/net/http/transport.go:1277 +0x68a
net/http.(*Transport).getConn()
/home/nuts/golang-test/go/src/net/http/transport.go:1231 +0x785
net/http.(*Transport).roundTrip()
/home/nuts/golang-test/go/src/net/http/transport.go:522 +0x83d
net/http.(*Transport).RoundTrip()
/home/nuts/golang-test/go/src/net/http/roundtrip.go:17 +0x42
net/http.send()
/home/nuts/golang-test/go/src/net/http/client.go:250 +0x6a8
net/http.(*Client).send()
/home/nuts/golang-test/go/src/net/http/client.go:174 +0x1ca
net/http.(*Client).do()
/home/nuts/golang-test/go/src/net/http/client.go:641 +0x2cc
main.sendRequest()
/home/nuts/golang-test/go/src/net/http/client.go:509 +0x11f
main.main.func1()
/home/nuts/golang-test/t.go:74 +0x80
Goroutine 21 (running) created at:
net/http.(*Transport).queueForDial()
/home/nuts/golang-test/go/src/net/http/transport.go:1277 +0x68a
net/http.(*Transport).getConn()
/home/nuts/golang-test/go/src/net/http/transport.go:1231 +0x785
net/http.(*Transport).roundTrip()
/home/nuts/golang-test/go/src/net/http/transport.go:522 +0x83d
net/http.(*Transport).RoundTrip()
/home/nuts/golang-test/go/src/net/http/roundtrip.go:17 +0x42
net/http.send()
/home/nuts/golang-test/go/src/net/http/client.go:250 +0x6a8
net/http.(*Client).send()
/home/nuts/golang-test/go/src/net/http/client.go:174 +0x1ca
net/http.(*Client).do()
/home/nuts/golang-test/go/src/net/http/client.go:641 +0x2cc
main.sendRequest()
/home/nuts/golang-test/go/src/net/http/client.go:509 +0x11f
main.main.func1()
/home/nuts/golang-test/t.go:74 +0x80