server: fix bug preventing Serve from exiting when Listener is closed (#1765)
This commit is contained in:
@ -479,8 +479,12 @@ func (s *Server) Serve(lis net.Listener) error {
|
|||||||
s.serveWG.Add(1)
|
s.serveWG.Add(1)
|
||||||
defer func() {
|
defer func() {
|
||||||
s.serveWG.Done()
|
s.serveWG.Done()
|
||||||
// Block until Stop or GracefulStop is ready for us to return.
|
select {
|
||||||
<-s.done
|
// Stop or GracefulStop called; block until done and return nil.
|
||||||
|
case <-s.quit:
|
||||||
|
<-s.done
|
||||||
|
default:
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
s.lis[lis] = true
|
s.lis[lis] = true
|
||||||
@ -526,7 +530,6 @@ func (s *Server) Serve(lis net.Listener) error {
|
|||||||
s.printf("done serving; Accept = %v", err)
|
s.printf("done serving; Accept = %v", err)
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
|
|
||||||
// If Stop or GracefulStop is called, return nil.
|
|
||||||
select {
|
select {
|
||||||
case <-s.quit:
|
case <-s.quit:
|
||||||
return nil
|
return nil
|
||||||
|
@ -5771,3 +5771,51 @@ func testCompressorRegister(t *testing.T, e env) {
|
|||||||
t.Fatalf("%v.Recv() = %v, want <nil>", stream, err)
|
t.Fatalf("%v.Recv() = %v, want <nil>", stream, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestServeExitsWhenListenerClosed(t *testing.T) {
|
||||||
|
defer leakcheck.Check(t)
|
||||||
|
|
||||||
|
ss := &stubServer{
|
||||||
|
emptyCall: func(context.Context, *testpb.Empty) (*testpb.Empty, error) {
|
||||||
|
return &testpb.Empty{}, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
s := grpc.NewServer()
|
||||||
|
testpb.RegisterTestServiceServer(s, ss)
|
||||||
|
|
||||||
|
lis, err := net.Listen("tcp", "localhost:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create listener: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
s.Serve(lis)
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
|
||||||
|
cc, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure(), grpc.WithBlock())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to dial server: %v", err)
|
||||||
|
}
|
||||||
|
defer cc.Close()
|
||||||
|
c := testpb.NewTestServiceClient(cc)
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
if _, err := c.EmptyCall(ctx, &testpb.Empty{}); err != nil {
|
||||||
|
t.Fatalf("Failed to send test RPC to server: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := lis.Close(); err != nil {
|
||||||
|
t.Fatalf("Failed to close listener: %v", err)
|
||||||
|
}
|
||||||
|
const timeout = 5 * time.Second
|
||||||
|
timer := time.NewTimer(timeout)
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
case <-timer.C:
|
||||||
|
t.Fatalf("Serve did not return after %v", timeout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user