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)