Use a lock to ensure that threaded code doesn't cause problems with proxy
authorZac Medico <zmedico@gentoo.org>
Sun, 22 Feb 2009 06:00:34 +0000 (06:00 -0000)
committerZac Medico <zmedico@gentoo.org>
Sun, 22 Feb 2009 06:00:34 +0000 (06:00 -0000)
registration and unregistration.

svn path=/main/trunk/; revision=12683

pym/portage/proxy/lazyimport.py

index 954b29d744ae2b5f7ee62d8c36e4b8fc057c307d..1a4a246ef908635c3cae0e3077ed82137ad52afc 100644 (file)
@@ -6,16 +6,27 @@ __all__ = ['lazyimport']
 
 import sys
 import types
+
+try:
+       import threading
+except ImportError:
+       import dummy_threading as threading
+
 from portage.proxy.objectproxy import ObjectProxy
 
 _module_proxies = {}
+_module_proxies_lock = threading.RLock()
 
 def _register_module_proxy(name, proxy):
-       proxy_list = _module_proxies.get(name)
-       if proxy_list is None:
-               proxy_list = []
-               _module_proxies[name] = proxy_list
-       proxy_list.append(proxy)
+       _module_proxies_lock.acquire()
+       try:
+               proxy_list = _module_proxies.get(name)
+               if proxy_list is None:
+                       proxy_list = []
+                       _module_proxies[name] = proxy_list
+               proxy_list.append(proxy)
+       finally:
+               _module_proxies_lock.release()
 
 def _unregister_module_proxy(name):
        """
@@ -24,20 +35,30 @@ def _unregister_module_proxy(name):
        destroy those proxies too. This way, destruction of a single proxy
        can trigger destruction of all the rest.
        """
-       proxy_list = _module_proxies.get(name)
-       if proxy_list is not None:
-               del _module_proxies[name]
-               for proxy in proxy_list:
-                       object.__getattribute__(proxy, '_get_target')()
-
-               modules = sys.modules
-               for name, proxy_list in list(_module_proxies.iteritems()):
-                       if name not in modules:
-                               continue
+       _module_proxies_lock.acquire()
+       try:
+               proxy_list = _module_proxies.get(name)
+               if proxy_list is not None:
+                       # First delete this name from the dict so that
+                       # if this same thread reenters below, it won't
+                       # enter this path again.
                        del _module_proxies[name]
                        for proxy in proxy_list:
                                object.__getattribute__(proxy, '_get_target')()
 
+                       modules = sys.modules
+                       for name, proxy_list in list(_module_proxies.iteritems()):
+                               if name not in modules:
+                                       continue
+                               # First delete this name from the dict so that
+                               # if this same thread reenters below, it won't
+                               # enter this path again.
+                               del _module_proxies[name]
+                               for proxy in proxy_list:
+                                       object.__getattribute__(proxy, '_get_target')()
+       finally:
+               _module_proxies_lock.release()
+
 class _LazyImport(ObjectProxy):
 
        __slots__ = ('_scope', '_alias', '_name', '_target')