Skip to content

Commit 5e0fa76

Browse files
authored
transport: make nextID accessed inside t.mu only (grpc#7148)
1 parent 54e0a13 commit 5e0fa76

File tree

1 file changed

+9
-7
lines changed

1 file changed

+9
-7
lines changed

internal/transport/http2_client.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,11 @@ type http2Client struct {
114114
streamQuota int64
115115
streamsQuotaAvailable chan struct{}
116116
waitingStreams uint32
117-
nextID uint32
118117
registeredCompressors string
119118

120119
// Do not access controlBuf with mu held.
121120
mu sync.Mutex // guard the following variables
121+
nextID uint32
122122
state transportState
123123
activeStreams map[uint32]*Stream
124124
// prevGoAway ID records the Last-Stream-ID in the previous GOAway frame.
@@ -808,22 +808,24 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream,
808808
t.waitingStreams--
809809
}
810810
t.streamQuota--
811+
812+
t.mu.Lock()
813+
if t.state == draining || t.activeStreams == nil { // Can be niled from Close().
814+
t.mu.Unlock()
815+
return false // Don't create a stream if the transport is already closed.
816+
}
817+
811818
hdr.streamID = t.nextID
812819
t.nextID += 2
813-
814820
// Drain client transport if nextID > MaxStreamID which signals gRPC that
815821
// the connection is closed and a new one must be created for subsequent RPCs.
816822
transportDrainRequired = t.nextID > MaxStreamID
817823

818824
s.id = hdr.streamID
819825
s.fc = &inFlow{limit: uint32(t.initialWindowSize)}
820-
t.mu.Lock()
821-
if t.state == draining || t.activeStreams == nil { // Can be niled from Close().
822-
t.mu.Unlock()
823-
return false // Don't create a stream if the transport is already closed.
824-
}
825826
t.activeStreams[s.id] = s
826827
t.mu.Unlock()
828+
827829
if t.streamQuota > 0 && t.waitingStreams > 0 {
828830
select {
829831
case t.streamsQuotaAvailable <- struct{}{}:

0 commit comments

Comments
 (0)