Commit fca3dd37 authored by Alex Brainman's avatar Alex Brainman

syscall: avoid convT2I allocs for ERROR_IO_PENDING instead of WSAEINPROGRESS

CL 28484 mistakenly assumed that WSARecv returns WSAEINPROGRESS
when there is nothing to read. But the error is ERROR_IO_PENDING.
Fix that mistake.

I was about to write a test for it. But I have found
TestTCPReadWriteAllocs in net package that does nearly what I need,
but was conveniently disabled. So enable and extend the test.

Fixes #16988

Change-Id: I55e5cf8998a9cf29e92b398d702280bdf7d6fc85
Reviewed-on: https://go-review.googlesource.com/28990
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent f15915af
...@@ -460,11 +460,9 @@ func TestTCPConcurrentAccept(t *testing.T) { ...@@ -460,11 +460,9 @@ func TestTCPConcurrentAccept(t *testing.T) {
func TestTCPReadWriteAllocs(t *testing.T) { func TestTCPReadWriteAllocs(t *testing.T) {
switch runtime.GOOS { switch runtime.GOOS {
case "nacl", "windows": case "nacl":
// NaCl needs to allocate pseudo file descriptor // NaCl needs to allocate pseudo file descriptor
// stuff. See syscall/fd_nacl.go. // stuff. See syscall/fd_nacl.go.
// Windows uses closures and channels for IO
// completion port-based netpoll. See fd_windows.go.
t.Skipf("not supported on %s", runtime.GOOS) t.Skipf("not supported on %s", runtime.GOOS)
} }
...@@ -474,7 +472,7 @@ func TestTCPReadWriteAllocs(t *testing.T) { ...@@ -474,7 +472,7 @@ func TestTCPReadWriteAllocs(t *testing.T) {
} }
defer ln.Close() defer ln.Close()
var server Conn var server Conn
errc := make(chan error) errc := make(chan error, 1)
go func() { go func() {
var err error var err error
server, err = ln.Accept() server, err = ln.Accept()
...@@ -489,6 +487,7 @@ func TestTCPReadWriteAllocs(t *testing.T) { ...@@ -489,6 +487,7 @@ func TestTCPReadWriteAllocs(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
defer server.Close() defer server.Close()
var buf [128]byte var buf [128]byte
allocs := testing.AllocsPerRun(1000, func() { allocs := testing.AllocsPerRun(1000, func() {
_, err := server.Write(buf[:]) _, err := server.Write(buf[:])
...@@ -503,6 +502,28 @@ func TestTCPReadWriteAllocs(t *testing.T) { ...@@ -503,6 +502,28 @@ func TestTCPReadWriteAllocs(t *testing.T) {
if allocs > 0 { if allocs > 0 {
t.Fatalf("got %v; want 0", allocs) t.Fatalf("got %v; want 0", allocs)
} }
var bufwrt [128]byte
ch := make(chan bool)
defer close(ch)
go func() {
for <-ch {
_, err := server.Write(bufwrt[:])
errc <- err
}
}()
allocs = testing.AllocsPerRun(1000, func() {
ch <- true
if _, err = io.ReadFull(client, buf[:]); err != nil {
t.Fatal(err)
}
if err := <-errc; err != nil {
t.Fatal(err)
}
})
if allocs > 0 {
t.Fatalf("got %v; want 0", allocs)
}
} }
func TestTCPStress(t *testing.T) { func TestTCPStress(t *testing.T) {
......
...@@ -831,12 +831,8 @@ var _ unsafe.Pointer ...@@ -831,12 +831,8 @@ var _ unsafe.Pointer
// Do the interface allocations only once for common // Do the interface allocations only once for common
// Errno values. // Errno values.
const (
errnoWSAEINPROGRESS = 10036
)
var ( var (
errWSAEINPROGRESS error = {{syscalldot}}Errno(errnoWSAEINPROGRESS) errERROR_IO_PENDING error = {{syscalldot}}Errno(ERROR_IO_PENDING)
) )
// errnoErr returns common boxed Errno values, to prevent // errnoErr returns common boxed Errno values, to prevent
...@@ -845,8 +841,8 @@ func errnoErr(e {{syscalldot}}Errno) error { ...@@ -845,8 +841,8 @@ func errnoErr(e {{syscalldot}}Errno) error {
switch e { switch e {
case 0: case 0:
return nil return nil
case errnoWSAEINPROGRESS: case ERROR_IO_PENDING:
return errWSAEINPROGRESS return errERROR_IO_PENDING
} }
// TODO: add more here, after collecting data on the common // TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running // error values see on Windows. (perhaps when running
......
...@@ -11,12 +11,8 @@ var _ unsafe.Pointer ...@@ -11,12 +11,8 @@ var _ unsafe.Pointer
// Do the interface allocations only once for common // Do the interface allocations only once for common
// Errno values. // Errno values.
const (
errnoWSAEINPROGRESS = 10036
)
var ( var (
errWSAEINPROGRESS error = Errno(errnoWSAEINPROGRESS) errERROR_IO_PENDING error = Errno(ERROR_IO_PENDING)
) )
// errnoErr returns common boxed Errno values, to prevent // errnoErr returns common boxed Errno values, to prevent
...@@ -25,8 +21,8 @@ func errnoErr(e Errno) error { ...@@ -25,8 +21,8 @@ func errnoErr(e Errno) error {
switch e { switch e {
case 0: case 0:
return nil return nil
case errnoWSAEINPROGRESS: case ERROR_IO_PENDING:
return errWSAEINPROGRESS return errERROR_IO_PENDING
} }
// TODO: add more here, after collecting data on the common // TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running // error values see on Windows. (perhaps when running
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment