fix(macos): don't panic on unexpected event types in keyboard callbacks#230
Open
paravozz wants to merge 1 commit intoRustAudio:masterfrom
Open
fix(macos): don't panic on unexpected event types in keyboard callbacks#230paravozz wants to merge 1 commit intoRustAudio:masterfrom
paravozz wants to merge 1 commit intoRustAudio:masterfrom
Conversation
`KeyboardState::process_native_event` is called by the macro-generated
`keyDown:` / `keyUp:` / `flagsChanged:` selectors in `view.rs`. The
state-matching on `event.eventType()` only covered NSKeyDown, NSKeyUp,
and NSFlagsChanged, falling through to `_ => unreachable!()` for
anything else.
AppKit occasionally dispatches non-key events into those selectors in
the wild (observed: `NSAppKitDefined` and `NSSystemDefined` events
during Cmd-Tab, input-source switches, modifier-repeat sequences, and
sleep/wake transitions). Because the selectors are generated as
`extern "C"`, hitting `unreachable!()` crosses the FFI boundary as
`panic_cannot_unwind` and aborts the hosting process. For plug-ins,
that crashes the DAW.
Evidence (Bitform 1.0.4 panic log, Ableton Live 12.3.6 on macOS,
2026-04-24):
info: panicked at library/core/src/panicking.rs:225:5:
panic in a function that cannot unwind
backtrace:
...
12: core::panicking::panic_nounwind
13: core::panicking::panic_cannot_unwind
14: flagsChanged
at src/macos/view.rs:81:9
Replace the unreachable with `return None` so the handler silently
drops events it can't interpret. There's nothing meaningful to
synthesize from an event that isn't a key or flags-changed, and
panicking from an `extern "C"` callback is never the right move.
The `NSFlagsChanged` arm already has a `return None` branch for the
non-modifier-key subcase (line 311), so the return-None pattern is
consistent with existing handling of uninteresting events.
paravozz
added a commit
to paravozz/baseview
that referenced
this pull request
Apr 25, 2026
…bitform) Applies RustAudio#232 (objc2 macros migration + four latent-bug fixes) on top of integration/bitform's existing four commits (keyboard-types bump, RustAudio#226 NSTextInputClient, RustAudio#228 hitTest first-click, RustAudio#230 panic-fix). Bitform's [patch.baseview] points at this branch via git source for downstream consumption while RustAudio#232 is in upstream review. Includes both the macros migration itself and the four latent-bug fixes (isARepeat gate, keyCode hoist, tracking-areas guard, three @encode mismatches), translated to apply on top of integration/bitform's NSTextInputClient additions (which RustAudio#232's upstream-PR base does not have, since RustAudio#232 is filed against upstream/master). Replaces 5816b44 (was a fixes-only-no-migration attempt) since that was the wrong shape; the integration branch needs the full migration to align with RustAudio#232's eventual landing. Becomes redundant when RustAudio#232 merges and vizia's baseview pin moves past it.
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.
Summary
KeyboardState::process_native_event(src/macos/keyboard.rs:282) is called from the macro-generatedkeyDown:/keyUp:/flagsChanged:selector implementations insrc/macos/view.rs:77. Thematch event.eventType()in the function only coversNSKeyDown,NSKeyUp, andNSFlagsChanged, falling through to_ => unreachable!()for anything else.Because the selector functions are generated as
extern "C", hittingunreachable!()crosses the FFI boundary aspanic_cannot_unwindand aborts the hosting process. For plug-ins, that crashes the DAW.Evidence
Captured from a baseview-based plug-in running in Ableton Live 12.3.6 on macOS, 2026-04-24:
(The inner panic frame that actually tripped
unreachable!()was optimized out; frame 14 is the FFI boundary function. Given the match structure, the unreachable is the candidate.)Why this hits in practice
AppKit occasionally dispatches non-key events into the key selectors during Cmd-Tab transitions, input-source switches, modifier-repeat sequences, and sleep/wake cycles. Even if the specific crash above was not
unreachable!()itself, any unexpectedNSEvent::eventType()value (NSAppKitDefined,NSSystemDefined, etc.) reaching this function is a latent crash.Fix
Replace
_ => unreachable!()with_ => return None. The handler silently drops events it cannot interpret. There is nothing meaningful to synthesize from an event that is not a key or flags-changed, and panicking from anextern "C"callback is never the right move.The
NSFlagsChangedarm above this already has areturn Nonebranch for the non-modifier-key subcase (line 311 on master), so the return-None fallback is consistent with existing handling of uninteresting events.Test plan
cargo check --features openglgreen.Local CI notes: the
cargo fmt --checkandcargo clippy -D warningserrors onmasterappear to be pre-existing (upstreamobjc 0.2.7'scargo-clippycfg warnings and awindow.rsformatting drift that I did not touch). Happy to adjust scope if you want the cfg-warning suppression bundled into this PR or handled separately.