mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
audio/internal/readerplayer: Bug fix: Potential deadlock when waveOutWrite failed (Windows)
This commit is contained in:
parent
f334eee1e4
commit
6c3c3533fb
@ -97,6 +97,7 @@ type players struct {
|
|||||||
context *context
|
context *context
|
||||||
players map[*playerImpl]struct{}
|
players map[*playerImpl]struct{}
|
||||||
buf []byte
|
buf []byte
|
||||||
|
err error
|
||||||
|
|
||||||
waveOut uintptr
|
waveOut uintptr
|
||||||
headers []*header
|
headers []*header
|
||||||
@ -114,6 +115,10 @@ func (p *players) add(player *playerImpl) error {
|
|||||||
p.cond.L.Lock()
|
p.cond.L.Lock()
|
||||||
defer p.cond.L.Unlock()
|
defer p.cond.L.Unlock()
|
||||||
|
|
||||||
|
if p.err != nil {
|
||||||
|
return p.err
|
||||||
|
}
|
||||||
|
|
||||||
if p.players == nil {
|
if p.players == nil {
|
||||||
p.players = map[*playerImpl]struct{}{}
|
p.players = map[*playerImpl]struct{}{}
|
||||||
}
|
}
|
||||||
@ -164,6 +169,13 @@ func (p *players) add(player *playerImpl) error {
|
|||||||
func (p *players) remove(player *playerImpl) error {
|
func (p *players) remove(player *playerImpl) error {
|
||||||
p.cond.L.Lock()
|
p.cond.L.Lock()
|
||||||
defer p.cond.L.Unlock()
|
defer p.cond.L.Unlock()
|
||||||
|
return p.removeImpl(player)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *players) removeImpl(player *playerImpl) error {
|
||||||
|
if p.err != nil {
|
||||||
|
return p.err
|
||||||
|
}
|
||||||
|
|
||||||
delete(p.players, player)
|
delete(p.players, player)
|
||||||
if len(p.players) > 0 {
|
if len(p.players) > 0 {
|
||||||
@ -221,10 +233,19 @@ func (p *players) loop() {
|
|||||||
if !p.wait() {
|
if !p.wait() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.readAndWriteBuffers()
|
if err := p.readAndWriteBuffers(); err != nil {
|
||||||
|
p.setError(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *players) setError(err error) {
|
||||||
|
p.cond.L.Lock()
|
||||||
|
defer p.cond.L.Unlock()
|
||||||
|
p.err = err
|
||||||
|
}
|
||||||
|
|
||||||
func (p *players) suspend() error {
|
func (p *players) suspend() error {
|
||||||
p.cond.L.Lock()
|
p.cond.L.Lock()
|
||||||
defer p.cond.L.Unlock()
|
defer p.cond.L.Unlock()
|
||||||
@ -261,13 +282,13 @@ var waveOutOpenCallback = windows.NewCallbackCDecl(func(hwo, uMsg, dwInstance, d
|
|||||||
return 0
|
return 0
|
||||||
})
|
})
|
||||||
|
|
||||||
func (p *players) readAndWriteBuffers() {
|
func (p *players) readAndWriteBuffers() error {
|
||||||
p.cond.L.Lock()
|
p.cond.L.Lock()
|
||||||
defer p.cond.L.Unlock()
|
defer p.cond.L.Unlock()
|
||||||
p.readAndWriteBuffersImpl()
|
return p.readAndWriteBuffersImpl()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *players) readAndWriteBuffersImpl() {
|
func (p *players) readAndWriteBuffersImpl() error {
|
||||||
headerNum := 0
|
headerNum := 0
|
||||||
for _, h := range p.headers {
|
for _, h := range p.headers {
|
||||||
if h.IsQueued() {
|
if h.IsQueued() {
|
||||||
@ -276,7 +297,7 @@ func (p *players) readAndWriteBuffersImpl() {
|
|||||||
headerNum++
|
headerNum++
|
||||||
}
|
}
|
||||||
if headerNum == 0 {
|
if headerNum == 0 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if n := headerBufferSize*headerNum - len(p.buf); n > 0 {
|
if n := headerBufferSize*headerNum - len(p.buf); n > 0 {
|
||||||
@ -360,13 +381,12 @@ func (p *players) readAndWriteBuffersImpl() {
|
|||||||
if werr := err.(*winmmError); werr.fname == "waveOutWrite" && werr.errno == errorNotFound {
|
if werr := err.(*winmmError); werr.fname == "waveOutWrite" && werr.errno == errorNotFound {
|
||||||
// TODO: Retry later.
|
// TODO: Retry later.
|
||||||
}
|
}
|
||||||
for pl := range p.players {
|
return err
|
||||||
pl.setError(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
p.buf = p.buf[headerBufferSize:]
|
p.buf = p.buf[headerBufferSize:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var thePlayers = players{
|
var thePlayers = players{
|
||||||
|
Loading…
Reference in New Issue
Block a user