@@ -363,6 +363,7 @@ func testServerMultipleGoAwayPendingRPC(t *testing.T, e env) {
363363 close (ch2 )
364364 }()
365365 // Loop until the server side GoAway signal is propagated to the client.
366+
366367 for {
367368 ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Millisecond )
368369 if _ , err := tc .EmptyCall (ctx , & testpb.Empty {}, grpc .WaitForReady (true )); err != nil {
@@ -402,6 +403,7 @@ func testServerMultipleGoAwayPendingRPC(t *testing.T, e env) {
402403 if err := stream .CloseSend (); err != nil {
403404 t .Fatalf ("%v.CloseSend() = %v, want <nil>" , stream , err )
404405 }
406+
405407 <- ch1
406408 <- ch2
407409 cancel ()
@@ -707,3 +709,59 @@ func (s) TestGoAwayStreamIDSmallerThanCreatedStreams(t *testing.T) {
707709 ct .writeGoAway (1 , http2 .ErrCodeNo , []byte {})
708710 goAwayWritten .Fire ()
709711}
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