mirror of
https://github.com/golang/go
synced 2024-11-12 06:30:21 -07:00
net: don't return io.EOF from zero byte reads
Updates #15735 Change-Id: I42ab2345443bbaeaf935d683460fc2c941b7679c Reviewed-on: https://go-review.googlesource.com/23227 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
c08436d1c8
commit
5bcdd63933
@ -201,6 +201,14 @@ func (fd *netFD) Read(p []byte) (n int, err error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
defer fd.readUnlock()
|
defer fd.readUnlock()
|
||||||
|
if len(p) == 0 {
|
||||||
|
// If the caller wanted a zero byte read, return immediately
|
||||||
|
// without trying. (But after acquiring the readLock.) Otherwise
|
||||||
|
// syscall.Read returns 0, nil and eofError turns that into
|
||||||
|
// io.EOF.
|
||||||
|
// TODO(bradfitz): make it wait for readability? (Issue 15735)
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
if err := fd.pd.prepareRead(); err != nil {
|
if err := fd.pd.prepareRead(); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -427,7 +427,9 @@ func (fd *netFD) Read(buf []byte) (int, error) {
|
|||||||
if race.Enabled {
|
if race.Enabled {
|
||||||
race.Acquire(unsafe.Pointer(&ioSync))
|
race.Acquire(unsafe.Pointer(&ioSync))
|
||||||
}
|
}
|
||||||
|
if len(buf) != 0 {
|
||||||
err = fd.eofError(n, err)
|
err = fd.eofError(n, err)
|
||||||
|
}
|
||||||
if _, ok := err.(syscall.Errno); ok {
|
if _, ok := err.(syscall.Errno); ok {
|
||||||
err = os.NewSyscallError("wsarecv", err)
|
err = os.NewSyscallError("wsarecv", err)
|
||||||
}
|
}
|
||||||
|
@ -360,3 +360,57 @@ func TestAcceptIgnoreAbortedConnRequest(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestZeroByteRead(t *testing.T) {
|
||||||
|
for _, network := range []string{"tcp", "unix", "unixpacket"} {
|
||||||
|
if !testableNetwork(network) {
|
||||||
|
t.Logf("skipping %s test", network)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ln, err := newLocalListener(network)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
connc := make(chan Conn, 1)
|
||||||
|
go func() {
|
||||||
|
defer ln.Close()
|
||||||
|
c, err := ln.Accept()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
connc <- c // might be nil
|
||||||
|
}()
|
||||||
|
c, err := Dial(network, ln.Addr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
sc := <-connc
|
||||||
|
if sc == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defer sc.Close()
|
||||||
|
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
// A zero byte read on Windows caused a wait for readability first.
|
||||||
|
// Rather than change that behavior, satisfy it in this test.
|
||||||
|
// See Issue 15735.
|
||||||
|
go io.WriteString(sc, "a")
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := c.Read(nil)
|
||||||
|
if n != 0 || err != nil {
|
||||||
|
t.Errorf("%s: zero byte client read = %v, %v; want 0, nil", network, n, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
// Same as comment above.
|
||||||
|
go io.WriteString(c, "a")
|
||||||
|
}
|
||||||
|
n, err = sc.Read(nil)
|
||||||
|
if n != 0 || err != nil {
|
||||||
|
t.Errorf("%s: zero byte server read = %v, %v; want 0, nil", network, n, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user