Skip to content

Commit

Permalink
streamer/audio: fixed a race condition in the BufferRead.Read method
Browse files Browse the repository at this point in the history
templates: fixed race conditions in the template reloading logic
  • Loading branch information
Wessie committed Feb 3, 2024
1 parent b0d9d25 commit 7bf98e8
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 20 deletions.
38 changes: 18 additions & 20 deletions streamer/audio/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package audio
import (
"io"
"sync"
"sync/atomic"
)

type AudioFormat struct {
Expand Down Expand Up @@ -93,44 +92,43 @@ func (b *Buffer) Error() (err error) {
// Reader returns a reader over the data contained in the buffer
func (b *Buffer) Reader() *BufferReader {
return &BufferReader{
mu: b.mu.RLocker(),
parent: b,
parentMu: b.mu.RLocker(),
parent: b,
}
}

// BufferReader is an io.Reader on top of a Buffer, multiple readers per
// Buffer can be created
type BufferReader struct {
mu sync.Mutex
// pos is the position of this reader in parent.buf
pos uint64

// mu is an inherited lock from the parent and should be locked when
// accessing the protected parent fields
mu sync.Locker
parentMu sync.Locker
// parent is the Buffer of this reader
parent *Buffer
}

func (br *BufferReader) Read(p []byte) (n int, err error) {
br.mu.Lock()

if br.pos == uint64(len(br.parent.buf)) {
if !br.parent.isClosed {
br.parent.cond.Wait()
} else if br.parent.err != nil {
err = br.parent.err
br.mu.Unlock()
return 0, err
br.mu.Lock() // write lock for ourselves
defer br.mu.Unlock()
br.parentMu.Lock() // read lock for parent
defer br.parentMu.Unlock()

for br.pos == uint64(len(br.parent.buf)) {
if br.parent.err != nil {
return 0, br.parent.err
}
if br.parent.isClosed {
return 0, io.EOF
}
}

n = copy(p, br.parent.buf[br.pos:])
if br.parent.isClosed && n == 0 {
br.mu.Unlock()
return 0, io.EOF
br.parent.cond.Wait()
}

atomic.AddUint64(&br.pos, uint64(n))
br.mu.Unlock()
n = copy(p, br.parent.buf[br.pos:])
br.pos += uint64(n)
return n, nil
}
1 change: 1 addition & 0 deletions streamer/audio/mp3_encode.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build !nolame
// +build !nolame

package audio
Expand Down
9 changes: 9 additions & 0 deletions templates/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ func (s *Site) Executor() *Executor {
}

func (s *Site) ThemeNames() []string {
s.mu.RLock()
defer s.mu.RUnlock()

keys := maps.Keys(s.themes)
slices.Sort(keys)
return keys
Expand Down Expand Up @@ -123,13 +126,19 @@ func (s *Site) prodTemplate(theme, page string) (*template.Template, error) {
}

func (s *Site) Theme(name string) ThemeBundle {
s.mu.RLock()
defer s.mu.RUnlock()

if ps, ok := s.themes[name]; ok {
return ps
}
return s.themes[DEFAULT_DIR]
}

func (s *Site) ResolveThemeName(name string) string {
s.mu.RLock()
defer s.mu.RUnlock()

if _, ok := s.themes[name]; ok {
return name
}
Expand Down

0 comments on commit 7bf98e8

Please sign in to comment.