@@ -322,8 +322,24 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
322
322
go func () {
323
323
t .loopy = newLoopyWriter (serverSide , t .framer , t .controlBuf , t .bdpEst , t .conn , t .logger )
324
324
t .loopy .ssGoAwayHandler = t .outgoingGoAwayHandler
325
- t .loopy .run ()
325
+ err := t .loopy .run ()
326
326
close (t .loopyWriterDone )
327
+ if ! isIOError (err ) {
328
+ // Close the connection if a non-I/O error occurs (for I/O errors
329
+ // the reader will also encounter the error and close). Wait 1
330
+ // second before closing the connection, or when the reader is done
331
+ // (i.e. the client already closed the connection or a connection
332
+ // error occurred). This avoids the potential problem where there
333
+ // is unread data on the receive side of the connection, which, if
334
+ // closed, would lead to a TCP RST instead of FIN, and the client
335
+ // encountering errors. For more info:
336
+ // https://github.com/grpc/grpc-go/issues/5358
337
+ select {
338
+ case <- t .readerDone :
339
+ case <- time .After (time .Second ):
340
+ }
341
+ t .conn .Close ()
342
+ }
327
343
}()
328
344
go t .keepalive ()
329
345
return t , nil
@@ -609,8 +625,8 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade
609
625
// traceCtx attaches trace to ctx and returns the new context.
610
626
func (t * http2Server ) HandleStreams (ctx context.Context , handle func (* Stream )) {
611
627
defer func () {
612
- <- t .loopyWriterDone
613
628
close (t .readerDone )
629
+ <- t .loopyWriterDone
614
630
}()
615
631
for {
616
632
t .controlBuf .throttle ()
@@ -1329,6 +1345,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) {
1329
1345
if err := t .framer .fr .WriteGoAway (sid , g .code , g .debugData ); err != nil {
1330
1346
return false , err
1331
1347
}
1348
+ t .framer .writer .Flush ()
1332
1349
if retErr != nil {
1333
1350
return false , retErr
1334
1351
}
@@ -1349,7 +1366,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) {
1349
1366
return false , err
1350
1367
}
1351
1368
go func () {
1352
- timer := time .NewTimer (time .Minute )
1369
+ timer := time .NewTimer (5 * time .Second )
1353
1370
defer timer .Stop ()
1354
1371
select {
1355
1372
case <- t .drainEvent .Done ():
0 commit comments