I've encountered a situation where NSUserDefaults is definitely not thread safe. Consider an user defaults value bound to an interface object. A background thread modifies this value, first acquiring the lock to write to the user defaults, writes the new value, and finally triggers a KVO notification, in turn triggering a call to the main thread to draw the updated value in the interface. Meanwhile the main thread wants to access a value in the user defaults too, but blocks on the lock because the background thread acquired it. The application is now deadlocked with both threads waiting on the other.

This is my understanding of what's happening in my app based on the following stack traces. An existing post mentions putting all access to NSUserDefaults in a @synchronized block. Before doing this, can anyone verify that that works?

Main Thread:
61 -[NSWindow makeKeyAndOrderFront:] + 189 (in AppKit) [0x95308afa] 61 -[NSWindow orderWindow:relativeTo:] + 105 (in AppKit) [0x953410d8] 61 -[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 1354 (in AppKit) [0x95341681] 61 - [NSWindow displayIfNeeded] + 189 (in AppKit) [0x95285ab9] 61 - [NSView displayIfNeeded] + 933 (in AppKit) [0x95285f09] 61 - [NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 3090 (in AppKit) [0x9534552d] 61 - [NSThemeFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView :] + 306 (in AppKit) [0x953489f7] 61 - [NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView :] + 759 (in AppKit) [0x953490b4] 61 -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 1902 (in AppKit) [0x9534aaa5]
                                                                                
...
61 -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 1050 (in AppKit) [0x9534a751] 61 -[NSTextView _drawRect:clip:] + 2579 (in AppKit) [0x953b07a6] 61 -[NSTextView drawRect:] + 250 (in AppKit) [0x953b09fd] 61 -[NSUserDefaults(NSUserDefaults) objectForKey:] + 36 (in Foundation) [0x91907524] 61 _semaphore_wait_signal_trap + 10 (in libSystem.B.dylib) [0x91403a2e]

Background Thread:
61 -[NSUserDefaults(NSUserDefaults) setObject:forKey:] + 113 (in Foundation) [0x91964821] 61 __CFXPreferencesSetValue + 102 (in CoreFoundation) [0x90966c46] 61 - [CFXPreferencesPropertyListSource setValue:forKey:] + 86 (in CoreFoundation) [0x90965f86] 61 - [NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 546 (in Foundation) [0x91907f22] 61 _NSKVONotify + 62 (in Foundation) [0x9198b58e] 61 -[NSController observeValueForKeyPath:ofObject:change:context:] + 949 (in AppKit) [0x95488920] 61 -[NSController _notifyObserversForKeyPath:change:] + 248 (in AppKit) [0x9526b15e] 61 - [NSObject(NSKeyValueObservingPrivate) _notifyObserversForKeyPath:change:] + 373 (in Foundation) [0x9191be45] 61 _NSKVONotify + 62 (in Foundation) [0x9198b58e] 61 -[NSEditableBinder _observeValueForKeyPath:ofObject:context:] + 124 (in AppKit) [0x9544ab24] 61 -[NSView _setHidden:] + 50 (in AppKit) [0x9527290d] 61 - [NSView(NSInternal) _setHidden:setNeedsDisplay:] + 1318 (in AppKit) [0x95272e3c] 61 -[NSView _invalidateGStatesForTree] + 49 (in AppKit) [0x9526648a] 61 -[NSView renewGState] + 50 (in AppKit) [0x95266690] 61 - [NSViewHierarchyLock lockForWritingWithExceptionHandler:] + 50 (in AppKit) [0x9589afed] 61 - [NSViewHierarchyLock _lockForWriting:handler:] + 416 (in AppKit) [0x9589b43d] 61 ___semwait_signal + 10 (in libSystem.B.dylib) [0x9140abce]

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to