From c7b5d1afc3c7d22675ae021fd41d3ecba90287c1 Mon Sep 17 00:00:00 2001 From: sergystepanov Date: Sat, 4 Feb 2023 22:47:53 +0300 Subject: [PATCH] Fix possible infinite loop on Mupen close (#389) For some reason the Libretro Mupen core breaks the pseudo-random order of channel selection leading to constant skip of the done channel on ticker aka an infinite loop. --- pkg/worker/emulator/libretro/frontend.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/pkg/worker/emulator/libretro/frontend.go b/pkg/worker/emulator/libretro/frontend.go index 4e4b64c6..4c550f69 100644 --- a/pkg/worker/emulator/libretro/frontend.go +++ b/pkg/worker/emulator/libretro/frontend.go @@ -128,9 +128,10 @@ func (f *Frontend) Start() { ticker := time.NewTicker(time.Second / time.Duration(nano.sysAvInfo.timing.fps)) defer func() { + f.log.Debug().Msgf("run loop cleanup") ticker.Stop() - nanoarchShutdown() f.mu.Lock() + nanoarchShutdown() frontend.canvas.Clear() f.SetAudio(noAudio) f.SetVideo(noVideo) @@ -141,13 +142,20 @@ func (f *Frontend) Start() { // start time for the first frame lastFrameTime = time.Now().UnixNano() for { + // selection from just two channels may freeze on + // ticker, ignoring the close chan for some reason select { - case <-ticker.C: - f.mu.Lock() - run() - f.mu.Unlock() case <-f.done: return + default: + select { + case <-ticker.C: + f.mu.Lock() + run() + f.mu.Unlock() + case <-f.done: + return + } } } } @@ -180,6 +188,7 @@ func (f *Frontend) SetViewport(width int, height int) { func (f *Frontend) ToggleMultitap() { toggleMultitap() } func (f *Frontend) Close() { + f.log.Debug().Msgf("frontend close called") close(f.done) frontend.stopped.Store(true) nano.reserved <- struct{}{}