Skip to content

Commit

Permalink
Fix race in StreamChannelCodecs()
Browse files Browse the repository at this point in the history
This fixes issue 2 of #294. The root cause is that the lock held when accessing `obj.Streams` is immediately released and doesn't cover accesses to the channels map.

To fix this somewhat elegantly, wrap the block that needs to access to the map in a function and hold the lock for the entire duration of the function.
  • Loading branch information
Robertof committed Feb 20, 2023
1 parent 82a88e1 commit 1b8d575
Showing 1 changed file with 16 additions and 12 deletions.
28 changes: 16 additions & 12 deletions storageStreamChannel.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,20 +131,24 @@ func (obj *StorageST) StreamChannelInfo(uuid string, channelID string) (*Channel
// StreamChannelCodecs get stream codec storage or wait
func (obj *StorageST) StreamChannelCodecs(streamID string, channelID string) ([]av.CodecData, error) {
for i := 0; i < 100; i++ {
obj.mutex.RLock()
tmp, ok := obj.Streams[streamID]
obj.mutex.RUnlock()
if !ok {
return nil, ErrorStreamNotFound
}
channelTmp, ok := tmp.Channels[channelID]
if !ok {
return nil, ErrorStreamChannelNotFound
}

if channelTmp.codecs != nil {
ret, err := (func() ([]av.CodecData, error) {
obj.mutex.RLock()
defer obj.mutex.RUnlock()
tmp, ok := obj.Streams[streamID]
if !ok {
return nil, ErrorStreamNotFound
}
channelTmp, ok := tmp.Channels[channelID]
if !ok {
return nil, ErrorStreamChannelNotFound
}
return channelTmp.codecs, nil
})()

if ret != nil || err != nil {
return ret, err
}

time.Sleep(50 * time.Millisecond)
}
return nil, ErrorStreamChannelCodecNotFound
Expand Down

0 comments on commit 1b8d575

Please sign in to comment.