Commit 77f21eea authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

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
parent 910caf93
...@@ -579,6 +579,8 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) { ...@@ -579,6 +579,8 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
} }
// Submit accept request. // Submit accept request.
fd.rio.Lock()
defer fd.rio.Unlock()
var o acceptOp var o acceptOp
o.Init(fd, 'r') o.Init(fd, 'r')
o.newsock = s o.newsock = s
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"runtime" "runtime"
"sync"
"testing" "testing"
"time" "time"
) )
...@@ -294,3 +295,35 @@ func TestIPv6LinkLocalUnicastTCP(t *testing.T) { ...@@ -294,3 +295,35 @@ func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
<-done <-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()
}
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