[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.


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]