Closed
Description
Originally reported as ipfs/kubo#3855 - my thanks to @timthelion, @whyrusleeping and others for helping debug.
What version of Go are you using (go version
)?
Tip go version devel +812b34efae Mon Sep 4 00:07:33 2017 +0000 darwin/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env
)?
$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/kevin"
GORACE=""
GOROOT="/Users/kevin/go"
GOTOOLDIR="/Users/kevin/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/sf/fsn3_vgd0n98r0jb86bgp83r0000gn/T/go-build607690397=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
What did you do?
Here's a test case exposing the error.
type failReader struct {
tot int64
limit int64
}
func (fr *failReader) Read(b []byte) (int, error) {
fr.tot += int64(len(b))
if fr.tot > fr.limit {
return 0, fmt.Errorf("look at my cool error")
}
return len(b), nil
}
func TestConnectionCloseManyFiles(t *testing.T) {
mux := NewServeMux()
mux.HandleFunc("/", func(w ResponseWriter, r *Request) {
buf := make([]byte, 4096)
var tot int64
_, err := w.Write([]byte("foobar"))
if err != nil {
t.Fatal(err)
}
w.(Flusher).Flush()
for {
n, err := r.Body.Read(buf)
if err != nil {
fmt.Println("read error: ", err)
fmt.Println("total bytes: ", tot)
break
}
//fmt.Println("total so far: ", tot)
tot += int64(n)
}
_, err = w.Write([]byte("foobar"))
if err != nil {
t.Fatal(err)
}
})
s := httptest.NewServer(mux)
r := &failReader{
limit: 1*1000*1000,
}
req, err := NewRequest("POST", s.URL, r)
if err != nil {
panic(err)
}
resp, err := DefaultClient.Do(req)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
buf := new(bytes.Buffer)
_, err = io.Copy(buf, resp.Body)
if err != nil {
t.Fatal(err)
}
if got := buf.String(); got != "foobar" {
t.Errorf("Write: got %s, want %s", got, "foobar")
}
}
You can tweak the numbers as you see fit; it takes about a million bytes read to trigger the error.
What did you expect to see?
I expect to see something like
client_test.go:1836: Post http://127.0.0.1:50390: look at my cool error
What did you see instead?
This odd error:
client_test.go:1843: read tcp 127.0.0.1:50389->127.0.0.1:50388: use of closed network connection