[pypy-svn] r46640 - in pypy/dist/pypy/module: __builtin__ thread/test

arigo at codespeak.net arigo at codespeak.net
Sat Sep 15 16:46:19 CEST 2007


Author: arigo
Date: Sat Sep 15 16:46:18 2007
New Revision: 46640

Modified:
   pypy/dist/pypy/module/__builtin__/importing.py
   pypy/dist/pypy/module/thread/test/test_import_lock.py
Log:
Make the import lock really more fine-grained (the previous attempt 
didn't achieve that).  Add a test, which is really an implementation 
test as CPython fails it.


Modified: pypy/dist/pypy/module/__builtin__/importing.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/importing.py	(original)
+++ pypy/dist/pypy/module/__builtin__/importing.py	Sat Sep 15 16:46:18 2007
@@ -196,16 +196,6 @@
 importhook.unwrap_spec = [ObjSpace,str,W_Root,W_Root,W_Root]
 
 def absolute_import(space, modulename, baselevel, w_fromlist, tentative):
-    lock = getimportlock(space)
-    acquired = lock.try_acquire_lock()
-    try:
-        return _absolute_import(space, modulename, baselevel,
-                                w_fromlist, tentative)
-    finally:
-        if acquired:
-            lock.release_lock()
-
-def _absolute_import(space, modulename, baselevel, w_fromlist, tentative):
     w = space.wrap
     
     w_mod = None
@@ -258,34 +248,42 @@
         w_mod = space.sys.getmodule(modulename) 
         if w_mod is not None:
             return w_mod
-        # Examin importhooks (PEP302) before doing the import
-        if w_path is not None:
-            w_loader  = find_module(space, w_modulename, w_path) 
-        else:
-            w_loader  = find_module(space, w_modulename, space.w_None)
-        if not space.is_w(w_loader, space.w_None):
-            w_mod = space.call_method(w_loader, "load_module", w_modulename)
-            #w_mod_ = check_sys_modules(space, w_modulename)
-            if w_mod is not None and w_parent is not None:
-                space.setattr(w_parent, w(partname), w_mod)
 
-            return w_mod
-        
-        
-        if w_path is not None:
-            for path in space.unpackiterable(w_path):
-                dir = os.path.join(space.str_w(path), partname)
-                if os.path.isdir(dir):
-                    fn = os.path.join(dir, '__init__')
+        lock = getimportlock(space)
+        acquired = lock.try_acquire_lock()
+        try:
+            # Examin importhooks (PEP302) before doing the import
+            if w_path is not None:
+                w_loader  = find_module(space, w_modulename, w_path) 
+            else:
+                w_loader  = find_module(space, w_modulename, space.w_None)
+            if not space.is_w(w_loader, space.w_None):
+                w_mod = space.call_method(w_loader, "load_module", w_modulename)
+                #w_mod_ = check_sys_modules(space, w_modulename)
+                if w_mod is not None and w_parent is not None:
+                    space.setattr(w_parent, w(partname), w_mod)
+
+                return w_mod
+            
+            
+            if w_path is not None:
+                for path in space.unpackiterable(w_path):
+                    dir = os.path.join(space.str_w(path), partname)
+                    if os.path.isdir(dir):
+                        fn = os.path.join(dir, '__init__')
+                        w_mod = try_import_mod(space, w_modulename, fn,
+                                               w_parent, w(partname),
+                                               pkgdir=dir)
+                        if w_mod is not None:
+                            return w_mod
+                    fn = os.path.join(space.str_w(path), partname)
                     w_mod = try_import_mod(space, w_modulename, fn, w_parent,
-                                           w(partname), pkgdir=dir)
+                                           w(partname))
                     if w_mod is not None:
                         return w_mod
-                fn = os.path.join(space.str_w(path), partname)
-                w_mod = try_import_mod(space, w_modulename, fn, w_parent,
-                                       w(partname))
-                if w_mod is not None:
-                    return w_mod
+        finally:
+            if acquired:
+                lock.release_lock()
 
     if tentative:
         return None
@@ -302,6 +300,8 @@
 # still being executed in another thread.
 
 class ImportRLock:
+    _ann_seen = False
+
     def __init__(self, space):
         self.space = space
         self.lock = None
@@ -312,12 +312,14 @@
         # run-time.
         self.lock = None
         assert self.lockowner is None
+        self._ann_seen = True
         return False
 
     def try_acquire_lock(self):
         # this function runs with the GIL acquired so there is no race
         # condition in the creation of the lock
         if self.lock is None:
+            assert not self._ann_seen
             self.lock = self.space.allocate_lock()
         me = self.space.getexecutioncontext()   # used as thread ident
         if self.lockowner is me:

Modified: pypy/dist/pypy/module/thread/test/test_import_lock.py
==============================================================================
--- pypy/dist/pypy/module/thread/test/test_import_lock.py	(original)
+++ pypy/dist/pypy/module/thread/test/test_import_lock.py	Sat Sep 15 16:46:18 2007
@@ -1,8 +1,14 @@
+from pypy.tool.udir import udir
 from pypy.module.thread.test.support import GenericTestThread
 
 
 class AppTestThread(GenericTestThread):
 
+    def setup_class(cls):
+        GenericTestThread.setup_class.im_func(cls)
+        tmpdir = str(udir.ensure('test_import_lock', dir=1))
+        cls.w_tmpdir = cls.space.wrap(tmpdir)
+
     def test_import_lock(self):
         import thread
         done = []
@@ -17,3 +23,24 @@
     def test_with_many_dependencies(self):
         import thread
         import re      # -> causes nested imports
+
+    def test_no_lock_for_reimporting(self):
+        # CPython deadlocks in this situation; in our case the property
+        # of not requiring the import lock for already-imported modules
+        # is useful for translation, to avoid needing a prebuilt import
+        # lock object.
+        import os, sys
+        f = open(os.path.join(self.tmpdir, 'foobaz1.py'), 'w')
+        print >> f, """if 1:
+            import thread
+            lock = thread.allocate_lock()
+            lock.acquire()
+            def f():
+                import sys
+                lock.release()
+            thread.start_new_thread(f, ())
+            lock.acquire()
+        """
+        f.close()
+        sys.path.insert(0, self.tmpdir)
+        import foobaz1



More information about the Pypy-commit mailing list