import (
"errors"
"fmt"
- "internal/testenv"
"io"
"net/internal/socktest"
"os"
// Issue 24808: verify that ECONNRESET is not temporary for read.
func TestNotTemporaryRead(t *testing.T) {
- if runtime.GOOS == "freebsd" {
- testenv.SkipFlaky(t, 25289)
- }
- if runtime.GOOS == "aix" {
- testenv.SkipFlaky(t, 29685)
- }
t.Parallel()
- server := func(cs *TCPConn) error {
- cs.SetLinger(0)
- // Give the client time to get stuck in a Read.
- time.Sleep(50 * time.Millisecond)
+
+ ln := newLocalListener(t, "tcp")
+ serverDone := make(chan struct{})
+ dialed := make(chan struct{})
+ go func() {
+ defer close(serverDone)
+
+ cs, err := ln.Accept()
+ if err != nil {
+ return
+ }
+ <-dialed
+ cs.(*TCPConn).SetLinger(0)
cs.Close()
- return nil
+
+ ln.Close()
+ }()
+ defer func() { <-serverDone }()
+
+ ss, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
}
- client := func(ss *TCPConn) error {
- _, err := ss.Read([]byte{0})
- if err == nil {
- return errors.New("Read succeeded unexpectedly")
- } else if err == io.EOF {
- // This happens on Plan 9.
- return nil
- } else if ne, ok := err.(Error); !ok {
- return fmt.Errorf("unexpected error %v", err)
- } else if ne.Temporary() {
- return fmt.Errorf("unexpected temporary error %v", err)
+ defer ss.Close()
+ close(dialed)
+ _, err = ss.Read([]byte{0})
+ if err == nil {
+ t.Fatal("Read succeeded unexpectedly")
+ } else if err == io.EOF {
+ // This happens on Plan 9, but for some reason (prior to CL 385314) it was
+ // accepted everywhere else too.
+ if runtime.GOOS == "plan9" {
+ return
}
- return nil
+ // TODO: during an open development cycle, try making this a failure
+ // and see whether it causes the test to become flaky anywhere else.
+ return
+ }
+ if ne, ok := err.(Error); !ok {
+ t.Errorf("Read error does not implement net.Error: %v", err)
+ } else if ne.Temporary() {
+ t.Errorf("Read error is unexpectedly temporary: %v", err)
}
- withTCPConnPair(t, client, server)
}
// The various errors should implement the Error interface.