@@ -26,6 +26,7 @@ import (
2626 "testing"
2727 "time"
2828
29+ "golang.org/x/net/http2"
2930 "google.golang.org/grpc"
3031 "google.golang.org/grpc/codes"
3132 "google.golang.org/grpc/credentials/insecure"
@@ -164,3 +165,53 @@ func (s) TestGracefulStop(t *testing.T) {
164165 cancel ()
165166 wg .Wait ()
166167}
168+
169+ func (s ) TestGracefulStopClosesConnAfterLastStream (t * testing.T ) {
170+ // This test ensures that a server closes the connections to its clients
171+ // when the final stream has completed after a GOAWAY.
172+
173+ handlerCalled := make (chan struct {})
174+ gracefulStopCalled := make (chan struct {})
175+
176+ ts := & funcServer {streamingInputCall : func (stream testpb.TestService_StreamingInputCallServer ) error {
177+ close (handlerCalled ) // Initiate call to GracefulStop.
178+ <- gracefulStopCalled // Wait for GOAWAYs to be received by the client.
179+ return nil
180+ }}
181+
182+ te := newTest (t , tcpClearEnv )
183+ te .startServer (ts )
184+ defer te .tearDown ()
185+
186+ te .withServerTester (func (st * serverTester ) {
187+ st .writeHeadersGRPC (1 , "/grpc.testing.TestService/StreamingInputCall" , false )
188+
189+ <- handlerCalled // Wait for the server to invoke its handler.
190+
191+ // Gracefully stop the server.
192+ gracefulStopDone := make (chan struct {})
193+ go func () {
194+ te .srv .GracefulStop ()
195+ close (gracefulStopDone )
196+ }()
197+ st .wantGoAway (http2 .ErrCodeNo ) // Server sends a GOAWAY due to GracefulStop.
198+ pf := st .wantPing () // Server sends a ping to verify client receipt.
199+ st .writePing (true , pf .Data ) // Send ping ack to confirm.
200+ st .wantGoAway (http2 .ErrCodeNo ) // Wait for subsequent GOAWAY to indicate no new stream processing.
201+
202+ close (gracefulStopCalled ) // Unblock server handler.
203+
204+ fr := st .wantAnyFrame () // Wait for trailer.
205+ hdr , ok := fr .(* http2.MetaHeadersFrame )
206+ if ! ok {
207+ t .Fatalf ("Received unexpected frame of type (%T) from server: %v; want HEADERS" , fr , fr )
208+ }
209+ if ! hdr .StreamEnded () {
210+ t .Fatalf ("Received unexpected HEADERS frame from server: %v; want END_STREAM set" , fr )
211+ }
212+
213+ st .wantRSTStream (http2 .ErrCodeNo ) // Server should send RST_STREAM because client did not half-close.
214+
215+ <- gracefulStopDone // Wait for GracefulStop to return.
216+ })
217+ }
0 commit comments