Skip to content

Commit 09fc336

Browse files
authored
server: fix bug preventing Serve from exiting when Listener is closed (grpc#1765)
1 parent 035eb47 commit 09fc336

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

server.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,12 @@ func (s *Server) Serve(lis net.Listener) error {
479479
s.serveWG.Add(1)
480480
defer func() {
481481
s.serveWG.Done()
482-
// Block until Stop or GracefulStop is ready for us to return.
483-
<-s.done
482+
select {
483+
// Stop or GracefulStop called; block until done and return nil.
484+
case <-s.quit:
485+
<-s.done
486+
default:
487+
}
484488
}()
485489

486490
s.lis[lis] = true
@@ -526,7 +530,6 @@ func (s *Server) Serve(lis net.Listener) error {
526530
s.printf("done serving; Accept = %v", err)
527531
s.mu.Unlock()
528532

529-
// If Stop or GracefulStop is called, return nil.
530533
select {
531534
case <-s.quit:
532535
return nil

test/end2end_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5771,3 +5771,51 @@ func testCompressorRegister(t *testing.T, e env) {
57715771
t.Fatalf("%v.Recv() = %v, want <nil>", stream, err)
57725772
}
57735773
}
5774+
5775+
func TestServeExitsWhenListenerClosed(t *testing.T) {
5776+
defer leakcheck.Check(t)
5777+
5778+
ss := &stubServer{
5779+
emptyCall: func(context.Context, *testpb.Empty) (*testpb.Empty, error) {
5780+
return &testpb.Empty{}, nil
5781+
},
5782+
}
5783+
5784+
s := grpc.NewServer()
5785+
testpb.RegisterTestServiceServer(s, ss)
5786+
5787+
lis, err := net.Listen("tcp", "localhost:0")
5788+
if err != nil {
5789+
t.Fatalf("Failed to create listener: %v", err)
5790+
}
5791+
5792+
done := make(chan struct{})
5793+
go func() {
5794+
s.Serve(lis)
5795+
close(done)
5796+
}()
5797+
5798+
cc, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure(), grpc.WithBlock())
5799+
if err != nil {
5800+
t.Fatalf("Failed to dial server: %v", err)
5801+
}
5802+
defer cc.Close()
5803+
c := testpb.NewTestServiceClient(cc)
5804+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
5805+
defer cancel()
5806+
if _, err := c.EmptyCall(ctx, &testpb.Empty{}); err != nil {
5807+
t.Fatalf("Failed to send test RPC to server: %v", err)
5808+
}
5809+
5810+
if err := lis.Close(); err != nil {
5811+
t.Fatalf("Failed to close listener: %v", err)
5812+
}
5813+
const timeout = 5 * time.Second
5814+
timer := time.NewTimer(timeout)
5815+
select {
5816+
case <-done:
5817+
return
5818+
case <-timer.C:
5819+
t.Fatalf("Serve did not return after %v", timeout)
5820+
}
5821+
}

0 commit comments

Comments
 (0)