1
0
mirror of https://github.com/golang/go synced 2024-10-02 14:28:38 -06:00

net: fix concurrent Accept on windows

Runtime netpoll supports at most one read waiter
and at most one write waiter. It's responsibility
of net package to ensure that. Currently windows
implementation allows more than one waiter in Accept.
It leads to "fatal error: netpollblock: double wait".

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/12400045
This commit is contained in:
Dmitriy Vyukov 2013-08-04 23:31:23 +04:00
parent 910caf9345
commit 77f21eea59
2 changed files with 35 additions and 0 deletions

View File

@ -579,6 +579,8 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
}
// Submit accept request.
fd.rio.Lock()
defer fd.rio.Unlock()
var o acceptOp
o.Init(fd, 'r')
o.newsock = s

View File

@ -8,6 +8,7 @@ import (
"fmt"
"reflect"
"runtime"
"sync"
"testing"
"time"
)
@ -294,3 +295,35 @@ func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
<-done
}
}
func TestTCPConcurrentAccept(t *testing.T) {
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
ln, err := Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Listen failed: %v", err)
}
const N = 10
var wg sync.WaitGroup
wg.Add(N)
for i := 0; i < N; i++ {
go func() {
for {
c, err := ln.Accept()
if err != nil {
break
}
c.Close()
}
wg.Done()
}()
}
for i := 0; i < 10*N; i++ {
c, err := Dial("tcp", ln.Addr().String())
if err != nil {
t.Fatalf("Dial failed: %v", err)
}
c.Close()
}
ln.Close()
wg.Wait()
}