[gtk-osx-users] Lion, NSUserDefaults, Threading, Python and Deadlock?



Hi Everyone, 

My application has been freezing on Lion (call trace below). This is a tentative heads-up for anyone using pygtk and the NSUserDefaults system on Lion. 

It appears that Lion has new asynchronous NSUserDefaults code(*) handled by the 'wqthread'. This looks to synchronise preferences in the background. However it tries to acquire the python GIL lock at some point, which I am assuming is in order to notify the module-global AppKit.NSUserDefaults.standardUserDefaults() object in my python code.

I suppose this is leading to deadlock as follows: 


  pygtk thread 
     - ACQUIRES GIL lock 
  [...]
  wqthread wakes up to synchronize preferences, 
     - ACQUIRES some NSUserDefaults lock
     - WAITS on GIL lock held by pygtk thread, I am assuming in order to notify my NSDefaults python object
  [..] 
  pygtk thread tries to do something with preferences 
     - WAITS on the same NSUserDefaults lock held by wqthread  


In this case gtk is reading the NSUserDefaults for the doubleClickThreshold in quartz/gdkevents-quartz.c (**) but I presume the same scenario could occur from my python level use, too.   

So, assuming this is right, what to do? 

  a) Break the GIL depedency: 
        - AppKit to relenquish GIL lock when accessing NSUserDefaults (via some specialcase workaround module?) 
        - asynchronous defaults update code to refrain from triggering a call into python
  b) Break the NSUserDefaults lock dependency: 
        - no go, as we need to serialise Preferences access at some level. 
  c) Limit the lifetime of my python NSUserDefaults object 
        - minimises but does not eliminate the problem as the same scenario can still occur. 
  d) Don't use NSUserDefaults in python or gtk 
 
        
... none of which are especially appealing.

best, 
Richard. 




Thread A: 
[...]
17 PyEval_EvalFrameEx + 11348 (in Python) [0xfbebc]
  17 _wrap_gtk_main + 119 (in _gtk.so) [0x85193d]
    [...]
      17 gtk_tree_view_button_press + 2077 (in libgtk-quartz-2.0.0.dylib) [0xb54eb8]
        17 g_object_get + 117 (in libgobject-2.0.0.dylib) [0x412024]
          17 g_object_get_valist + 491 (in libgobject-2.0.0.dylib) [0x411e65]
            17 gtk_settings_get_property + 351 (in libgtk-quartz-2.0.0.dylib) [0xabfedc]
              17 gdk_screen_get_setting + 155 (in libgdk-quartz-2.0.0.dylib) [0xda6bf6]
                17 -[NSUserDefaults(NSUserDefaults) floatForKey:] + 42 (in Foundation) [0x9a94eb8d]
                  17 -[NSUserDefaults(NSUserDefaults) objectForKey:] + 36 (in Foundation) [0x9a92b02a]
                    17 CFPreferencesCopyAppValue + 153 (in CoreFoundation) [0x9a583fc9]
                      17 __psynch_rw_rdlock + 10 (in libsystem_kernel.dylib) [0x98aa98ca]

Thread B: 
[...]
17 __-[CFXPreferencesPropertyListSource synchronizeInBackgroundWithCompletionBlock:]_block_invoke_1 + 191 (in CoreFoundation) [0x9a5bb8cf]
  17 -[CFXPreferencesPropertyListSource _assimilateSync:] + 79 (in CoreFoundation) [0x9a578c6f]
    17 CFRelease + 577 (in CoreFoundation) [0x9a5348e1]
      17 __CFBasicHashDrain + 528 (in CoreFoundation) [0x9a538ad0]
        17 __CFDictionaryStandardReleaseKey + 79 (in CoreFoundation) [0x9a542c7f]
          17 CFRelease + 169 (in CoreFoundation) [0x9a534749]
            17 ??? (in _objc.so) [0x2729523]
              17 PyGILState_Ensure + 109 (in Python) [0x115bae]
                17 PyEval_RestoreThread + 73 (in Python) [0xfec5e]
                  17 PyThread_acquire_lock + 119 (in Python) [0x1206e4]
                    [...] 

(*) http://developer.apple.com/library/mac/#releasenotes/Cocoa/Foundation.html
(**) http://git.gnome.org/browse/gtk+/tree/gdk/quartz/gdkevents-quartz.c?h=gtk-2-24-quartz



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]