diff --git a/docs/src/content/docs/changelog.mdx b/docs/src/content/docs/changelog.mdx index 982a5b464..0ceda3213 100644 --- a/docs/src/content/docs/changelog.mdx +++ b/docs/src/content/docs/changelog.mdx @@ -55,6 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Pass build flags to binding generator by [@fbbdev](https://github.com/fbbdev) in [#4023](https://github.com/wailsapp/wails/pull/4023) - Change paths in windows Taskfile to forward slashes to ensure it works on non-Windows platforms by [@leaanthony](https://github.com/leaanthony) - Mac + Mac JS events now fixed by [@leaanthony](https://github.com/leaanthony) +- Fixed event deadlock for macOS by [@leaanthony](https://github.com/leaanthony) ### Changed diff --git a/v3/pkg/application/webview_window.go b/v3/pkg/application/webview_window.go index 7776f7280..1a37643bb 100644 --- a/v3/pkg/application/webview_window.go +++ b/v3/pkg/application/webview_window.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "runtime" + "slices" "strings" "sync" @@ -738,20 +739,21 @@ func (w *WebviewWindow) Center() { // OnWindowEvent registers a callback for the given window event func (w *WebviewWindow) OnWindowEvent(eventType events.WindowEventType, callback func(event *WindowEvent)) func() { eventID := uint(eventType) - w.eventListenersLock.Lock() - defer w.eventListenersLock.Unlock() windowEventListener := &WindowEventListener{ callback: callback, } + w.eventListenersLock.Lock() w.eventListeners[eventID] = append(w.eventListeners[eventID], windowEventListener) + w.eventListenersLock.Unlock() if w.impl != nil { w.impl.on(eventID) } return func() { + // Check if eventListener is already locked w.eventListenersLock.Lock() - defer w.eventListenersLock.Unlock() w.eventListeners[eventID] = lo.Without(w.eventListeners[eventID], windowEventListener) + w.eventListenersLock.Unlock() } } @@ -773,9 +775,6 @@ func (w *WebviewWindow) RegisterHook(eventType events.WindowEventType, callback } func (w *WebviewWindow) HandleWindowEvent(id uint) { - w.eventListenersLock.RLock() - defer w.eventListenersLock.RUnlock() - // Get hooks w.eventHooksLock.RLock() hooks := w.eventHooks[id] @@ -791,7 +790,12 @@ func (w *WebviewWindow) HandleWindowEvent(id uint) { } } - for _, listener := range w.eventListeners[id] { + // Copy the w.eventListeners + w.eventListenersLock.RLock() + var tempListeners = slices.Clone(w.eventListeners[id]) + w.eventListenersLock.RUnlock() + + for _, listener := range tempListeners { go func() { defer handlePanic() listener.callback(thisEvent)