Commit 645e77ef authored by Mikio Hara's avatar Mikio Hara

net/internal/socktest: fix data race

Fixes #10796.

Change-Id: Ifcd2e771c64114e210fbfc5efaaceb53c534f745
Reviewed-on: https://go-review.googlesource.com/10007Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 647026a1
...@@ -9,6 +9,7 @@ package socktest_test ...@@ -9,6 +9,7 @@ package socktest_test
import ( import (
"net/internal/socktest" "net/internal/socktest"
"os" "os"
"sync"
"syscall" "syscall"
"testing" "testing"
) )
...@@ -27,6 +28,21 @@ func TestMain(m *testing.M) { ...@@ -27,6 +28,21 @@ func TestMain(m *testing.M) {
os.Exit(st) os.Exit(st)
} }
func TestSwitch(t *testing.T) {
const N = 10
var wg sync.WaitGroup
wg.Add(N)
for i := 0; i < N; i++ {
go func() {
defer wg.Done()
for _, family := range []int{syscall.AF_INET, syscall.AF_INET6} {
socketFunc(family, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
}
}()
}
wg.Wait()
}
func TestSocket(t *testing.T) { func TestSocket(t *testing.T) {
for _, f := range []socktest.Filter{ for _, f := range []socktest.Filter{
func(st *socktest.Status) (socktest.AfterFilter, error) { return nil, nil }, func(st *socktest.Status) (socktest.AfterFilter, error) { return nil, nil },
......
...@@ -10,12 +10,6 @@ import ( ...@@ -10,12 +10,6 @@ import (
"sync" "sync"
) )
func switchInit(sw *Switch) {
sw.fltab = make(map[FilterType]Filter)
sw.sotab = make(Sockets)
sw.stats = make(stats)
}
// A Switch represents a callpath point switch for socket system // A Switch represents a callpath point switch for socket system
// calls. // calls.
type Switch struct { type Switch struct {
...@@ -29,6 +23,12 @@ type Switch struct { ...@@ -29,6 +23,12 @@ type Switch struct {
stats stats stats stats
} }
func (sw *Switch) init() {
sw.fltab = make(map[FilterType]Filter)
sw.sotab = make(Sockets)
sw.stats = make(stats)
}
// Stats returns a list of per-cookie socket statistics. // Stats returns a list of per-cookie socket statistics.
func (sw *Switch) Stats() []Stat { func (sw *Switch) Stats() []Stat {
var st []Stat var st []Stat
...@@ -162,7 +162,7 @@ func (f AfterFilter) apply(st *Status) error { ...@@ -162,7 +162,7 @@ func (f AfterFilter) apply(st *Status) error {
// Set deploys the socket system call filter f for the filter type t. // Set deploys the socket system call filter f for the filter type t.
func (sw *Switch) Set(t FilterType, f Filter) { func (sw *Switch) Set(t FilterType, f Filter) {
sw.once.Do(func() { switchInit(sw) }) sw.once.Do(sw.init)
sw.fmu.Lock() sw.fmu.Lock()
sw.fltab[t] = f sw.fltab[t] = f
sw.fmu.Unlock() sw.fmu.Unlock()
......
...@@ -22,7 +22,7 @@ func (sw *Switch) sockso(s int) *Status { ...@@ -22,7 +22,7 @@ func (sw *Switch) sockso(s int) *Status {
// addLocked returns a new Status without locking. // addLocked returns a new Status without locking.
// sw.smu must be held before call. // sw.smu must be held before call.
func (sw *Switch) addLocked(s, family, sotype, proto int) *Status { func (sw *Switch) addLocked(s, family, sotype, proto int) *Status {
sw.once.Do(func() { switchInit(sw) }) sw.once.Do(sw.init)
so := Status{Cookie: cookie(family, sotype, proto)} so := Status{Cookie: cookie(family, sotype, proto)}
sw.sotab[s] = so sw.sotab[s] = so
return &so return &so
......
...@@ -22,7 +22,7 @@ func (sw *Switch) sockso(s syscall.Handle) *Status { ...@@ -22,7 +22,7 @@ func (sw *Switch) sockso(s syscall.Handle) *Status {
// addLocked returns a new Status without locking. // addLocked returns a new Status without locking.
// sw.smu must be held before call. // sw.smu must be held before call.
func (sw *Switch) addLocked(s syscall.Handle, family, sotype, proto int) *Status { func (sw *Switch) addLocked(s syscall.Handle, family, sotype, proto int) *Status {
sw.once.Do(func() { switchInit(sw) }) sw.once.Do(sw.init)
so := Status{Cookie: cookie(family, sotype, proto)} so := Status{Cookie: cookie(family, sotype, proto)}
sw.sotab[s] = so sw.sotab[s] = so
return &so return &so
......
...@@ -10,6 +10,8 @@ import "syscall" ...@@ -10,6 +10,8 @@ import "syscall"
// Socket wraps syscall.Socket. // Socket wraps syscall.Socket.
func (sw *Switch) Socket(family, sotype, proto int) (s int, err error) { func (sw *Switch) Socket(family, sotype, proto int) (s int, err error) {
sw.once.Do(sw.init)
so := &Status{Cookie: cookie(family, sotype, proto)} so := &Status{Cookie: cookie(family, sotype, proto)}
sw.fmu.RLock() sw.fmu.RLock()
f, _ := sw.fltab[FilterSocket] f, _ := sw.fltab[FilterSocket]
......
...@@ -8,6 +8,8 @@ import "syscall" ...@@ -8,6 +8,8 @@ import "syscall"
// Socket wraps syscall.Socket. // Socket wraps syscall.Socket.
func (sw *Switch) Socket(family, sotype, proto int) (s syscall.Handle, err error) { func (sw *Switch) Socket(family, sotype, proto int) (s syscall.Handle, err error) {
sw.once.Do(sw.init)
so := &Status{Cookie: cookie(family, sotype, proto)} so := &Status{Cookie: cookie(family, sotype, proto)}
sw.fmu.RLock() sw.fmu.RLock()
f, _ := sw.fltab[FilterSocket] f, _ := sw.fltab[FilterSocket]
......
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