fix(desktop): keep AppKit assertions in the accent-frame paint from aborting the app - #550
Merged
Merged
Conversation
…borting the app A crash report (macOS 26.5.1, v0.3.2) showed the app dying with SIGABRT: an AppKit assertion (NSAssertionHandler out of -[NSView dealloc]) fired while apply_accent_frame repainted a window, and the Objective-C exception unwound through the Rust frames into std::terminate. The trigger is a set_accent_frame IPC landing on a window whose view hierarchy is mid-teardown (the compose window closes at will), where the paint's transient retain of the content view can be the release that runs -[NSView dealloc] on this stack. Two layers of defense, both scoped to the accent frame: - Run the whole AppKit paint (split out as paint_accent_frame) under objc2::exception::catch, so an AppKit assertion now costs one skipped, logged repaint instead of the process. Needs the objc2 "exception" feature; the crate builds with the default panic=unwind, which the catch requires. - Skip painting when the content view is already detached from its window (content.window() == nil), the mid-teardown state that made the final-release dealloc possible in the first place. Also reattaches the "Draw the per-workspace identity frame" doc block to the paint function — it had been left fused onto window_corner_radius's doc when that helper was inserted between the comment and the function.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes a SIGABRT crash reported on macOS 26.5.1 (v0.3.2): an AppKit assertion (
NSAssertionHandlerout of-[NSView dealloc]) fired whileapply_accent_framerepainted a window, and the Objective-C exception unwound through the Rust frames intostd::terminate, taking the whole app down.Trigger. The crashed stack shows a live
set_accent_frameIPC (WKWebView didPostMessage → handle_ipc_message → set_accent_frame → run_on_main_thread → apply_accent_frame) landing on a window whose view hierarchy is mid-teardown — the compose window closes at will, racing in-flight accent updates. In that state the paint's transient retain of the content view can be the release that runs-[NSView dealloc]on this stack, and AppKit's dealloc assertion throws.Fix. Two layers, both scoped to the accent frame:
paint_accent_frame) underobjc2::exception::catch, so an AppKit assertion now costs one skipped, logged repaint instead of the process. Needs the objc2exceptionfeature (added in Cargo.toml — feature-only, no lockfile change); the crate builds with the defaultpanic=unwind, which the catch requires.content.window()is nil), the mid-teardown state that made the final-release dealloc possible in the first place.Also reattaches the "Draw the per-workspace identity frame" doc block to the paint function — it had been left fused onto
window_corner_radius's doc when that helper was inserted between the comment and the function.Verified locally: desktop TS bridge lint/typecheck/tests (37 passing, unaffected by the Rust-only change). The Rust side compiles only in Desktop CI here (no local toolchain), so the macos-14
cargo fmt --check+cargo testjob is the compile gate.