swarm/pss: fix data race in notify_test.go (TestStart)

TestStart failed when all tests were run with race detection.
Simplest way to reproduce:
`go test -race -count 1 -run TestStart ./swarm/pss/notify`

The handler passed to `ctrlClient.Subscribe` is run in a goroutine,
started in `p2p.(*Peer).startProtocols()`. There were 2 problems/races
cased by the handler closure:
1. `t.Fatalf` was called from a goroutine
2. `updateMsg` passed to the handler (reda) was later modified in the
main thread (write)

fixes ethersphere/go-ethereum#1158
This commit is contained in:
Ferenc Szabo 2019-01-24 12:11:52 +01:00
parent dc43ea8d03
commit 6f80218492

View file

@ -128,7 +128,7 @@ func TestStart(t *testing.T) {
defer rightSub.Unsubscribe() defer rightSub.Unsubscribe()
updateC := make(chan []byte) updateC := make(chan []byte)
updateMsg := []byte{} var updateMsg []byte
ctrlClient := NewController(psses[rightPub]) ctrlClient := NewController(psses[rightPub])
ctrlNotifier := NewController(psses[leftPub]) ctrlNotifier := NewController(psses[leftPub])
ctrlNotifier.NewNotifier("foo.eth", 2, updateC) ctrlNotifier.NewNotifier("foo.eth", 2, updateC)
@ -145,17 +145,24 @@ func TestStart(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
copyOfUpdateMsg := make([]byte, len(updateMsg))
copy(copyOfUpdateMsg, updateMsg)
ctrlClientError := make(chan error, 1)
ctrlClient.Subscribe(rsrcName, pubkey, addrbytes, func(s string, b []byte) error { ctrlClient.Subscribe(rsrcName, pubkey, addrbytes, func(s string, b []byte) error {
if s != "foo.eth" || !bytes.Equal(updateMsg, b) { if s != "foo.eth" || !bytes.Equal(copyOfUpdateMsg, b) {
t.Fatalf("unexpected result in client handler: '%s':'%x'", s, b) ctrlClientError <- fmt.Errorf("unexpected result in client handler: '%s':'%x'", s, b)
} else {
log.Info("client handler receive", "s", s, "b", b)
} }
log.Info("client handler receive", "s", s, "b", b)
return nil return nil
}) })
var inMsg *pss.APIMsg var inMsg *pss.APIMsg
select { select {
case inMsg = <-rmsgC: case inMsg = <-rmsgC:
case err := <-ctrlClientError:
t.Fatal(err)
case <-ctx.Done(): case <-ctx.Done():
t.Fatal(ctx.Err()) t.Fatal(ctx.Err())
} }