You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@thrift.apache.org by "Zach Wasserman (JIRA)" <ji...@apache.org> on 2017/06/30 17:24:00 UTC
[jira] [Created] (THRIFT-4243) Go TSimpleServer race on wait in
Stop() method
Zach Wasserman created THRIFT-4243:
--------------------------------------
Summary: Go TSimpleServer race on wait in Stop() method
Key: THRIFT-4243
URL: https://issues.apache.org/jira/browse/THRIFT-4243
Project: Thrift
Issue Type: Bug
Components: Go - Library
Reporter: Zach Wasserman
Synchronization issues with the use of {{sync.WaitGroup}} in the {{TSimpleServer}} implementation set off the race detector. Note the docs (https://godoc.org/sync#WaitGroup.Add) specify "calls with a positive delta that occur when the counter is zero must happen before a Wait".
The following unit test demonstrates the issue:
{code}
package thrift
import (
"testing"
"time"
)
type mockProcessor struct {
ProcessFunc func(in, out TProtocol) (bool, TException)
}
func (m *mockProcessor) Process(in, out TProtocol) (bool, TException) {
return m.ProcessFunc(in, out)
}
type mockServerTransport struct {
ListenFunc func() error
AcceptFunc func() (TTransport, error)
CloseFunc func() error
InterruptFunc func() error
}
func (m *mockServerTransport) Listen() error {
return m.ListenFunc()
}
func (m *mockServerTransport) Accept() (TTransport, error) {
return m.AcceptFunc()
}
func (m *mockServerTransport) Close() error {
return m.CloseFunc()
}
func (m *mockServerTransport) Interrupt() error {
return m.InterruptFunc()
}
type mockTTransport struct {
TTransport
}
func (m *mockTTransport) Close() error {
return nil
}
func TestWaitRace(t *testing.T) {
proc := &mockProcessor{
ProcessFunc: func(in, out TProtocol) (bool, TException) {
return false, nil
},
}
trans := &mockServerTransport{
ListenFunc: func() error {
return nil
},
AcceptFunc: func() (TTransport, error) {
return &mockTTransport{}, nil
},
CloseFunc: func() error {
return nil
},
InterruptFunc: func() error {
return nil
},
}
serv := NewTSimpleServer2(proc, trans)
go serv.Serve()
time.Sleep(1)
serv.Stop()
}
{code}
When run with the race detector, this test produces the following output:
{code}
go test -race -v -run TestWaitRace -count 1
=== RUN TestWaitRace
==================
WARNING: DATA RACE
Write at 0x00c4200849f4 by goroutine 6:
internal/race.Write()
/usr/local/Cellar/go/1.8/libexec/src/internal/race/race.go:41 +0x38
sync.(*WaitGroup).Wait()
/usr/local/Cellar/go/1.8/libexec/src/sync/waitgroup.go:129 +0x14b
git.apache.org/thrift.git/lib/go/thrift.(*TSimpleServer).Stop.func1()
/Users/zwass/dev/go/src/git.apache.org/thrift.git/lib/go/thrift/simple_server.go:164 +0x9b
sync.(*Once).Do()
/usr/local/Cellar/go/1.8/libexec/src/sync/once.go:44 +0xe1
git.apache.org/thrift.git/lib/go/thrift.(*TSimpleServer).Stop()
/Users/zwass/dev/go/src/git.apache.org/thrift.git/lib/go/thrift/simple_server.go:166 +0x8c
git.apache.org/thrift.git/lib/go/thrift.TestWaitRace()
/Users/zwass/dev/go/src/git.apache.org/thrift.git/lib/go/thrift/simple_server_test.go:134 +0x1be
testing.tRunner()
/usr/local/Cellar/go/1.8/libexec/src/testing/testing.go:657 +0x107
Previous read at 0x00c4200849f4 by goroutine 7:
internal/race.Read()
/usr/local/Cellar/go/1.8/libexec/src/internal/race/race.go:37 +0x38
sync.(*WaitGroup).Add()
/usr/local/Cellar/go/1.8/libexec/src/sync/waitgroup.go:71 +0x26b
git.apache.org/thrift.git/lib/go/thrift.(*TSimpleServer).AcceptLoop()
/Users/zwass/dev/go/src/git.apache.org/thrift.git/lib/go/thrift/simple_server.go:139 +0xa6
git.apache.org/thrift.git/lib/go/thrift.(*TSimpleServer).Serve()
/Users/zwass/dev/go/src/git.apache.org/thrift.git/lib/go/thrift/simple_server.go:154 +0x86
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/local/Cellar/go/1.8/libexec/src/testing/testing.go:697 +0x543
testing.runTests.func1()
/usr/local/Cellar/go/1.8/libexec/src/testing/testing.go:882 +0xaa
testing.tRunner()
/usr/local/Cellar/go/1.8/libexec/src/testing/testing.go:657 +0x107
testing.runTests()
/usr/local/Cellar/go/1.8/libexec/src/testing/testing.go:888 +0x4e0
testing.(*M).Run()
/usr/local/Cellar/go/1.8/libexec/src/testing/testing.go:822 +0x1c3
main.main()
git.apache.org/thrift.git/lib/go/thrift/_test/_testmain.go:266 +0x20f
Goroutine 7 (running) created at:
git.apache.org/thrift.git/lib/go/thrift.TestWaitRace()
/Users/zwass/dev/go/src/git.apache.org/thrift.git/lib/go/thrift/simple_server_test.go:132 +0x1a3
testing.tRunner()
/usr/local/Cellar/go/1.8/libexec/src/testing/testing.go:657 +0x107
==================
--- FAIL: TestWaitRace (0.15s)
testing.go:610: race detected during execution of test
panic: sync: WaitGroup is reused before previous Wait has returned [recovered]
panic: sync: WaitGroup is reused before previous Wait has returned
goroutine 5 [running]:
testing.tRunner.func1(0xc42006aea0)
/usr/local/Cellar/go/1.8/libexec/src/testing/testing.go:622 +0x55f
panic(0x14aea60, 0xc4201896a0)
/usr/local/Cellar/go/1.8/libexec/src/runtime/panic.go:489 +0x2f0
sync.(*WaitGroup).Wait(0xc4200849e8)
/usr/local/Cellar/go/1.8/libexec/src/sync/waitgroup.go:133 +0x138
git.apache.org/thrift.git/lib/go/thrift.(*TSimpleServer).Stop.func1()
/Users/zwass/dev/go/src/git.apache.org/thrift.git/lib/go/thrift/simple_server.go:164 +0x9c
sync.(*Once).Do(0x174ce68, 0xc42002bf00)
/usr/local/Cellar/go/1.8/libexec/src/sync/once.go:44 +0xe2
git.apache.org/thrift.git/lib/go/thrift.(*TSimpleServer).Stop(0xc420084980, 0x153af90, 0xc420084980)
/Users/zwass/dev/go/src/git.apache.org/thrift.git/lib/go/thrift/simple_server.go:166 +0x8d
git.apache.org/thrift.git/lib/go/thrift.TestWaitRace(0xc42006aea0)
/Users/zwass/dev/go/src/git.apache.org/thrift.git/lib/go/thrift/simple_server_test.go:134 +0x1bf
testing.tRunner(0xc42006aea0, 0x153b2b0)
/usr/local/Cellar/go/1.8/libexec/src/testing/testing.go:657 +0x108
created by testing.(*T).Run
/usr/local/Cellar/go/1.8/libexec/src/testing/testing.go:697 +0x544
exit status 2
FAIL git.apache.org/thrift.git/lib/go/thrift 0.190s
{code}
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)