From dd0ec492e48bd5d6d2b51766af29f5f2b65421ea Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 5 Apr 2024 10:00:38 -0700 Subject: [PATCH] macos: wrap syncAppearance in async call Fixes #1656 When called as part of window restoration AppKit has a lock, so NSAppearance changes need to be called async. See deadlock: ``` Thread 1 Queue : com.apple.main-thread (serial) 0 0x000000018fd63fac in __ulock_wait () 1 0x00000001069bf720 in _dlock_wait () 2 0x00000001069bfaec in _dispatch_group_wait_slow () 3 0x0000000106b5f5c4 in interposed_dispatch_group_wait () 4 0x00000001937fb1f0 in NSCGSTransactionRunPreCommitActions_ () 5 0x00000001938f1230 in -[_NSCGSTransaction synchronize] () 6 0x00000001938f11ac in NSCGSTransactionSynchronize () 7 0x000000019382ad30 in +[NSCGSWindow(NSCGSSpace) isAnyWindowOnAVisibleSpace:] () 8 0x000000019382a968 in -[NSWindow _isInSomeVisibleSpace] () 9 0x000000019382a8e4 in -[NSWindow isOnActiveSpace] () 10 0x0000000193db8d98 in -[NSApplication(NSApplicationAppearance_Internal) _invalidateWindowAppearances] () 11 0x00000001938f44d4 in -[NSApplication(NSAppearanceCustomization) setAppearance:] () 12 0x0000000102c48050 in AppDelegate.syncAppearance() at /Users/mitchellh/code/go/src/github.com/mitchellh/ghostty/macos/Sources/App/macOS/AppDelegate.swift:412 13 0x0000000102c47840 in AppDelegate.configDidReload(_:) at /Users/mitchellh/code/go/src/github.com/mitchellh/ghostty/macos/Sources/App/macOS/AppDelegate.swift:380 14 0x0000000102c43c7c in AppDelegate.applicationDidFinishLaunching(_:) at /Users/mitchellh/code/go/src/github.com/mitchellh/ghostty/macos/Sources/App/macOS/AppDelegate.swift:110 ``` --- macos/Sources/App/macOS/AppDelegate.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/macos/Sources/App/macOS/AppDelegate.swift b/macos/Sources/App/macOS/AppDelegate.swift index 5f70c6ce6..34b4ba2b8 100644 --- a/macos/Sources/App/macOS/AppDelegate.swift +++ b/macos/Sources/App/macOS/AppDelegate.swift @@ -374,8 +374,10 @@ class AppDelegate: NSObject, syncMenuShortcuts() terminalManager.relabelAllTabs() - // Config could change window appearance - syncAppearance() + // Config could change window appearance. We wrap this in an async queue because when + // this is called as part of application launch it can deadlock with an internal + // AppKit mutex on the appearance. + DispatchQueue.main.async { self.syncAppearance() } // Update all of our windows terminalManager.windows.forEach { window in