@@ -363,6 +363,7 @@ func testServerMultipleGoAwayPendingRPC(t *testing.T, e env) {
363
363
close (ch2 )
364
364
}()
365
365
// Loop until the server side GoAway signal is propagated to the client.
366
+
366
367
for {
367
368
ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Millisecond )
368
369
if _ , err := tc .EmptyCall (ctx , & testpb.Empty {}, grpc .WaitForReady (true )); err != nil {
@@ -402,6 +403,7 @@ func testServerMultipleGoAwayPendingRPC(t *testing.T, e env) {
402
403
if err := stream .CloseSend (); err != nil {
403
404
t .Fatalf ("%v.CloseSend() = %v, want <nil>" , stream , err )
404
405
}
406
+
405
407
<- ch1
406
408
<- ch2
407
409
cancel ()
@@ -707,3 +709,59 @@ func (s) TestGoAwayStreamIDSmallerThanCreatedStreams(t *testing.T) {
707
709
ct .writeGoAway (1 , http2 .ErrCodeNo , []byte {})
708
710
goAwayWritten .Fire ()
709
711
}
712
+
713
+ // TestTwoGoAwayPingFrames tests the scenario where you get two go away ping
714
+ // frames from the client during graceful shutdown. This should not crash the
715
+ // server.
716
+ func (s ) TestTwoGoAwayPingFrames (t * testing.T ) {
717
+ lis , err := net .Listen ("tcp" , "localhost:0" )
718
+ if err != nil {
719
+ t .Fatalf ("Failed to listen: %v" , err )
720
+ }
721
+ defer lis .Close ()
722
+ s := grpc .NewServer ()
723
+ defer s .Stop ()
724
+ go s .Serve (lis )
725
+
726
+ conn , err := net .DialTimeout ("tcp" , lis .Addr ().String (), defaultTestTimeout )
727
+ if err != nil {
728
+ t .Fatalf ("Failed to dial: %v" , err )
729
+ }
730
+
731
+ st := newServerTesterFromConn (t , conn )
732
+ st .greet ()
733
+ pingReceivedClientSide := testutils .NewChannel ()
734
+ go func () {
735
+ for {
736
+ f , err := st .readFrame ()
737
+ if err != nil {
738
+ return
739
+ }
740
+ switch f .(type ) {
741
+ case * http2.GoAwayFrame :
742
+ case * http2.PingFrame :
743
+ pingReceivedClientSide .Send (nil )
744
+ default :
745
+ t .Errorf ("server tester received unexpected frame type %T" , f )
746
+ }
747
+ }
748
+ }()
749
+ gsDone := testutils .NewChannel ()
750
+ go func () {
751
+ s .GracefulStop ()
752
+ gsDone .Send (nil )
753
+ }()
754
+ ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
755
+ defer cancel ()
756
+ if _ , err := pingReceivedClientSide .Receive (ctx ); err != nil {
757
+ t .Fatalf ("Error waiting for ping frame client side from graceful shutdown: %v" , err )
758
+ }
759
+ // Write two goaway pings here.
760
+ st .writePing (true , [8 ]byte {1 , 6 , 1 , 8 , 0 , 3 , 3 , 9 })
761
+ st .writePing (true , [8 ]byte {1 , 6 , 1 , 8 , 0 , 3 , 3 , 9 })
762
+ // Close the conn to finish up the Graceful Shutdown process.
763
+ conn .Close ()
764
+ if _ , err := gsDone .Receive (ctx ); err != nil {
765
+ t .Fatalf ("Error waiting for graceful shutdown of the server: %v" , err )
766
+ }
767
+ }
0 commit comments