Skip to content

Commit 2f784bb

Browse files
committed
http2: fix leak in activeRes by removing activeRes
AFAICT, activeRes serves no real purpose. It is used in just two ways: - To reduce the number of calls to closeIfIdle, which reduces the number of acquires of cc.mu when there are many concurrent streams. I dug through the CL history and could not find any benchmarks showing that this is necessary. - To avoid redundant calls to cs.bufPipe.CloseWithError(err) when a read loop is shutdown. This is unnecessary, since redundant CloseWithError calls are ignored. Since there isn't a good reason to have activeRes, the simplest way to fix the leak is to remove activeRes entirely. Updates golang/go#21543 Change-Id: I1d1d2dc6c946425a2772c8bf71436707021ac269 Reviewed-on: https://go-review.googlesource.com/80137 Reviewed-by: Brad Fitzpatrick <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 2e7c6d4 commit 2f784bb

File tree

1 file changed

+3
-15
lines changed

1 file changed

+3
-15
lines changed

transport.go

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,17 +1376,12 @@ func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
13761376
// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
13771377
type clientConnReadLoop struct {
13781378
cc *ClientConn
1379-
activeRes map[uint32]*clientStream // keyed by streamID
13801379
closeWhenIdle bool
13811380
}
13821381

13831382
// readLoop runs in its own goroutine and reads and dispatches frames.
13841383
func (cc *ClientConn) readLoop() {
1385-
rl := &clientConnReadLoop{
1386-
cc: cc,
1387-
activeRes: make(map[uint32]*clientStream),
1388-
}
1389-
1384+
rl := &clientConnReadLoop{cc: cc}
13901385
defer rl.cleanup()
13911386
cc.readerErr = rl.run()
13921387
if ce, ok := cc.readerErr.(ConnectionError); ok {
@@ -1441,10 +1436,8 @@ func (rl *clientConnReadLoop) cleanup() {
14411436
} else if err == io.EOF {
14421437
err = io.ErrUnexpectedEOF
14431438
}
1444-
for _, cs := range rl.activeRes {
1445-
cs.bufPipe.CloseWithError(err)
1446-
}
14471439
for _, cs := range cc.streams {
1440+
cs.bufPipe.CloseWithError(err) // no-op if already closed
14481441
select {
14491442
case cs.resc <- resAndError{err: err}:
14501443
default:
@@ -1522,7 +1515,7 @@ func (rl *clientConnReadLoop) run() error {
15221515
}
15231516
return err
15241517
}
1525-
if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 {
1518+
if rl.closeWhenIdle && gotReply && maybeIdle {
15261519
cc.closeIfIdle()
15271520
}
15281521
}
@@ -1578,9 +1571,6 @@ func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
15781571
// (nil, nil) special case. See handleResponse docs.
15791572
return nil
15801573
}
1581-
if res.Body != noBody {
1582-
rl.activeRes[cs.ID] = cs
1583-
}
15841574
cs.resTrailer = &res.Trailer
15851575
cs.resc <- resAndError{res: res}
15861576
return nil
@@ -1919,7 +1909,6 @@ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
19191909
rl.closeWhenIdle = true
19201910
}
19211911
cs.bufPipe.closeWithErrorAndCode(err, code)
1922-
delete(rl.activeRes, cs.ID)
19231912

19241913
select {
19251914
case cs.resc <- resAndError{err: err}:
@@ -2046,7 +2035,6 @@ func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
20462035
cs.bufPipe.CloseWithError(err)
20472036
cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
20482037
}
2049-
delete(rl.activeRes, cs.ID)
20502038
return nil
20512039
}
20522040

0 commit comments

Comments
 (0)