fix race condition in flow control manager

This commit is contained in:
Marten Seemann
2017-02-08 14:18:36 +07:00
parent 291e6c1344
commit 1ed5f30817

View File

@@ -138,6 +138,7 @@ func (f *flowControlManager) AddBytesRead(streamID protocol.StreamID, n protocol
func (f *flowControlManager) GetWindowUpdates() (res []WindowUpdate) {
f.mutex.Lock()
defer f.mutex.Unlock()
connFlowController := f.streamFlowController[0]
// get WindowUpdates for streams
@@ -161,8 +162,9 @@ func (f *flowControlManager) GetWindowUpdates() (res []WindowUpdate) {
}
func (f *flowControlManager) GetReceiveWindow(streamID protocol.StreamID) (protocol.ByteCount, error) {
f.mutex.Lock()
defer f.mutex.Unlock()
f.mutex.RLock()
defer f.mutex.RUnlock()
flowController, err := f.getFlowController(streamID)
if err != nil {
return 0, err
@@ -172,10 +174,10 @@ func (f *flowControlManager) GetReceiveWindow(streamID protocol.StreamID) (proto
// streamID must not be 0 here
func (f *flowControlManager) AddBytesSent(streamID protocol.StreamID, n protocol.ByteCount) error {
// Only lock the part reading from the map, since send-windows are only accessed from the session goroutine.
f.mutex.Lock()
defer f.mutex.Unlock()
fc, err := f.getFlowController(streamID)
f.mutex.Unlock()
if err != nil {
return err
}
@@ -190,10 +192,10 @@ func (f *flowControlManager) AddBytesSent(streamID protocol.StreamID, n protocol
// must not be called with StreamID 0
func (f *flowControlManager) SendWindowSize(streamID protocol.StreamID) (protocol.ByteCount, error) {
// Only lock the part reading from the map, since send-windows are only accessed from the session goroutine.
f.mutex.RLock()
defer f.mutex.RUnlock()
fc, err := f.getFlowController(streamID)
f.mutex.RUnlock()
if err != nil {
return 0, err
}
@@ -207,24 +209,23 @@ func (f *flowControlManager) SendWindowSize(streamID protocol.StreamID) (protoco
}
func (f *flowControlManager) RemainingConnectionWindowSize() protocol.ByteCount {
// Only lock the part reading from the map, since send-windows are only accessed from the session goroutine.
f.mutex.RLock()
res := f.streamFlowController[0].SendWindowSize()
f.mutex.RUnlock()
return res
defer f.mutex.RUnlock()
return f.streamFlowController[0].SendWindowSize()
}
// streamID may be 0 here
func (f *flowControlManager) UpdateWindow(streamID protocol.StreamID, offset protocol.ByteCount) (bool, error) {
// Only lock the part reading from the map, since send-windows are only accessed from the session goroutine.
f.mutex.Lock()
streamFlowController, err := f.getFlowController(streamID)
f.mutex.Unlock()
defer f.mutex.Unlock()
fc, err := f.getFlowController(streamID)
if err != nil {
return false, err
}
return streamFlowController.UpdateSendWindow(offset), nil
return fc.UpdateSendWindow(offset), nil
}
func (f *flowControlManager) getFlowController(streamID protocol.StreamID) (*flowController, error) {