Skip to content
This repository has been archived by the owner on Mar 5, 2023. It is now read-only.

EXC_BAD_ACCESS on Monterey when using swift String for defaultsKey #175

Open
timbertson opened this issue May 5, 2022 · 0 comments
Open

Comments

@timbertson
Copy link

After upgrading to MacOS monterey, I consistently saw the following crash in slinger, a window management app I maintain.

lldb shows the stacktrace as follows:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
  * frame #0: 0x0000000100922ae4 CoreFoundation`CFGetTypeID + 4
    frame #1: 0x00007ff820bbfe47 libswiftCore.dylib`_swift_stdlib_isNSString + 39
    frame #2: 0x00007ff8209d98ad libswiftCore.dylib`Swift.__StringStorage.isEqualToString(to: Swift.Optional<Swift.AnyObject>) -> Swift.Int8 + 125
    frame #3: 0x00007ff8209d9a12 libswiftCore.dylib`@objc Swift.__StringStorage.isEqualToString(to: Swift.Optional<Swift.AnyObject>) -> Swift.Int8 + 18
    frame #4: 0x00007ff813401e9b CoreFoundation`-[__NSDictionaryM __setObject:forKey:] + 573
    frame #5: 0x00007ff81341dcbc CoreFoundation`-[__NSFrozenDictionaryM __apply:context:] + 112
    frame #6: 0x00007ff81346226a CoreFoundation`___CFPrefsDeliverPendingKVONotificationsGuts_block_invoke + 324
    frame #7: 0x00007ff81346211e CoreFoundation`__CFDictionaryApplyFunction_block_invoke + 22
    frame #8: 0x00007ff81342aee3 CoreFoundation`CFBasicHashApply + 115
    frame #9: 0x00007ff81341dc0b CoreFoundation`CFDictionaryApplyFunction + 131
    frame #10: 0x00007ff813462093 CoreFoundation`_CFPrefsDeliverPendingKVONotificationsGuts + 262
    frame #11: 0x00007ff81340e9a6 CoreFoundation`-[_CFXPreferences _deliverPendingKVONotifications] + 90
    frame #12: 0x00007ff813548888 CoreFoundation`-[_CFXPreferences withNamedVolatileSourceForIdentifier:perform:] + 286
    frame #13: 0x00007ff813424932 CoreFoundation`__41-[_CFXPreferences registerDefaultValues:]_block_invoke + 98
    frame #14: 0x00007ff81340db9a CoreFoundation`withKeysAndValues + 268
    frame #15: 0x00007ff8134248b5 CoreFoundation`-[_CFXPreferences registerDefaultValues:] + 79
    frame #16: 0x00007ff813424836 CoreFoundation`_CFXPreferencesRegisterDefaultValues + 75
    frame #17: 0x00007ff81425b650 Foundation`-[NSUserDefaults(NSUserDefaults) registerDefaults:] + 255
    frame #18: 0x000000010001b0e5 Slinger`__46-[MASShortcutBinder registerDefaultShortcuts:]_block_invoke(.block_descriptor=<unavailable>, defaultsKey=<unavailable>, shortcut=<unavailable>, stop=<unavailable>) at MASShortcutBinder.m:77:9 [opt]
    frame #19: 0x00007ff820ad6751 libswiftCore.dylib`function signature specialization <Arg[0] = Dead> of Swift._SwiftDeferredNSDictionary.enumerateKeysAndObjects(options: Swift.Int, using: @convention(block) (Swift.Unmanaged<Swift.AnyObject>, Swift.Unmanaged<Swift.AnyObject>, Swift.UnsafeMutablePointer<Swift.UInt8>) -> ()) -> () + 321
    frame #20: 0x00007ff8208c70f5 libswiftCore.dylib`@objc Swift._SwiftDeferredNSDictionary.enumerateKeysAndObjects(options: Swift.Int, using: @convention(block) (Swift.Unmanaged<Swift.AnyObject>, Swift.Unmanaged<Swift.AnyObject>, Swift.UnsafeMutablePointer<Swift.UInt8>) -> ()) -> () + 37
    frame #21: 0x000000010001af9f Slinger`-[MASShortcutBinder registerDefaultShortcuts:](self=<unavailable>, _cmd=<unavailable>, defaultShortcuts=<unavailable>) at MASShortcutBinder.m:75:5 [opt]
    frame #22: 0x000000010001d22d Slinger`bind #1 (pref=<unavailable>, key=<unavailable>, modifiers=<unavailable>, slow=false, fn=0x000000010001f0c0 Slinger`closure #1 () -> () in bind(_: Swift.String, key: Swift.String, modifiers: __C.NSEventModifierFlags, action: Swift.String, arguments: Swift.Array<Any>, slow: Swift.Bool) -> ()partial apply forwarder with unmangled suffix ".32", keycodeMap=Swift.Dictionary<Swift.String, Swift.Array<Slinger.Keybinding.AMKeyCode>> @ 0x00007ff7bfefcfb0, status=0x0000600001729540) in ApplicationDelegate.run() at AppDelegate.swift:29:42 [opt]

I figured the obvious suspects were bad serialization, a sneaky nil somewhere, or threading. But I couldn't find any of those.

Eventually I took the stacktrace at its word - the fact it's doing string comparisons implies it's something to do with the key of the NSDictionary, nothing to do with the value.

Somehow I turned up this thread from 7 years ago: https://stackoverflow.com/questions/24208594/swift-string-manipulation-causing-exc-bad-access
It's slightly different, yet the same fix works - pass an NSString key instead of a swift String.

Here's the actual fix I made to slinger: timbertson/Slinger.app@dc55f53

I think this may have something to do with the binding code as well, given the presence of ___CFPrefsDeliverPendingKVONotificationsGuts_block_invoke. If I comment out the actual binder.bindShortcut(...) call it doesn't happen, but that may be a red herring. Oh, and the original crash happened when setting up the second keybinding. I.e. it works once, but fails after the first binding set up.

Anyway, I don't know if you want to investigate, feel free to close. I just figured it might at least help some poor soul googling for the same issue.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant