python: Ensure greater concurrency is wsgidir.
[ashd.git] / python3 / ashd / wsgidir.py
index f101117..031952b 100644 (file)
@@ -37,7 +37,7 @@ must, of course, be importable). When writing such handler functions,
 you will probably want to use the getmod() function in this module.
 """
 
 you will probably want to use the getmod() function in this module.
 """
 
-import os, threading, types
+import os, threading, types, importlib
 from . import wsgiutil
 
 __all__ = ["application", "wmain", "getmod", "cachedmod"]
 from . import wsgiutil
 
 __all__ = ["application", "wmain", "getmod", "cachedmod"]
@@ -55,7 +55,7 @@ class cachedmod(object):
     Additional data attributes can be arbitrarily added for recording
     any meta-data about the module.
     """
     Additional data attributes can be arbitrarily added for recording
     any meta-data about the module.
     """
-    def __init__(self, mod, mtime):
+    def __init__(self, mod = None, mtime = -1):
         self.lock = threading.Lock()
         self.mod = mod
         self.mtime = mtime
         self.lock = threading.Lock()
         self.mod = mod
         self.mtime = mtime
@@ -87,35 +87,30 @@ def getmod(path):
     about the module. See its documentation for details.
     """
     sb = os.stat(path)
     about the module. See its documentation for details.
     """
     sb = os.stat(path)
-    cachelock.acquire()
-    try:
+    with cachelock:
         if path in modcache:
             entry = modcache[path]
         if path in modcache:
             entry = modcache[path]
-            if sb.st_mtime <= entry.mtime:
-                return entry
-        
-        f = open(path)
-        try:
-            text = f.read()
-        finally:
-            f.close()
-        code = compile(text, path, "exec")
-        mod = types.ModuleType(mangle(path))
-        mod.__file__ = path
-        exec(code, mod.__dict__)
-        entry = cachedmod(mod, sb.st_mtime)
-        modcache[path] = entry
+        else:
+            entry = cachedmod()
+            modcache[path] = entry
+    with entry.lock:
+        if entry.mod is None or sb.st_mtime > entry.mtime:
+            with open(path, "rb") as f:
+                text = f.read()
+            code = compile(text, path, "exec")
+            mod = types.ModuleType(mangle(path))
+            mod.__file__ = path
+            exec(code, mod.__dict__)
+            entry.mod = mod
+            entry.mtime = sb.st_mtime
         return entry
         return entry
-    finally:
-        cachelock.release()
 
 def chain(env, startreq):
     path = env["SCRIPT_FILENAME"]
     mod = getmod(path)
     entry = None
     if mod is not None:
 
 def chain(env, startreq):
     path = env["SCRIPT_FILENAME"]
     mod = getmod(path)
     entry = None
     if mod is not None:
-        mod.lock.acquire()
-        try:
+        with mod.lock:
             if hasattr(mod, "entry"):
                 entry = mod.entry
             else:
             if hasattr(mod, "entry"):
                 entry = mod.entry
             else:
@@ -124,12 +119,11 @@ def chain(env, startreq):
                 elif hasattr(mod.mod, "application"):
                     entry = mod.mod.application
                 mod.entry = entry
                 elif hasattr(mod.mod, "application"):
                     entry = mod.mod.application
                 mod.entry = entry
-        finally:
-            mod.lock.release()
     if entry is not None:
         return entry(env, startreq)
     return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "Invalid WSGI handler.")
 exts["wsgi"] = chain
     if entry is not None:
         return entry(env, startreq)
     return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "Invalid WSGI handler.")
 exts["wsgi"] = chain
+exts["wsgi3"] = chain
 
 def addext(ext, handler):
     p = handler.rindex('.')
 
 def addext(ext, handler):
     p = handler.rindex('.')