Skip navigation.
 
mlNSUserDefaults, threads, and binding
FROM : Greg Hoover
DATE : Wed Apr 16 22:10:33 2008

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]

Related mailsAuthorDate
No related mails found.