Uploaded image for project: 'Thrift'
  1. Thrift
  2. THRIFT-4240

Go TSimpleServer does not close properly

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 0.10.0
    • 0.11.0
    • Go - Library
    • None

    Description

      Improper use of sync.Once results in only the first call to Close() in a given process actually executing.

      The sync.Once object should be a struct member, and not package global.

      Test:

      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()
      }
      
      func TestMultipleStop(t *testing.T) {
      	proc := &mockProcessor{
      		ProcessFunc: func(in, out TProtocol) (bool, TException) {
      			return false, nil
      		},
      	}
      
      	var interruptCalled bool
      	c := make(chan struct{})
      	trans := &mockServerTransport{
      		ListenFunc: func() error {
      			return nil
      		},
      		AcceptFunc: func() (TTransport, error) {
      			<-c
      			return nil, nil
      		},
      		CloseFunc: func() error {
      			c <- struct{}{}
      			return nil
      		},
      		InterruptFunc: func() error {
      			interruptCalled = true
      			return nil
      		},
      	}
      
      	serv := NewTSimpleServer2(proc, trans)
      	go serv.Serve()
      	serv.Stop()
      	if !interruptCalled {
      		t.Error("first server transport should have been interrupted")
      	}
      
      	serv = NewTSimpleServer2(proc, trans)
      	interruptCalled = false
      	go serv.Serve()
      	serv.Stop()
      	if !interruptCalled {
      		t.Error("second server transport should have been interrupted")
      	}
      }
      

      Output:

      go test -race -run TestMultipleStop
      --- FAIL: TestMultipleStop (0.00s)
      	simple_server_test.go:96: second server transport should have been interrupted
      FAIL
      exit status 1
      FAIL	github.com/kolide/launcher/vendor/git.apache.org/thrift.git/lib/go/thrift	0.020s
      

      Attachments

        Issue Links

          Activity

            People

              zwass Zach Wasserman
              zwass Zach Wasserman
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: