We've looked into the problem a bit deeper.. There is a problem but
it's different than what was in the first post.

The problem seems to be in the locking of the session file:
Two processes/requests open the same session file for write and thus
get a handle on it

One request gets the portalocker lock on the session file, the other
one blocks and waits for the first request to release the lock.

The first request writes the changes to the session file, and releases
the lock.
The second request then gets the lock, but still uses the old file
handle and results in an EOFError exception


The first patch improved the situation, because the file is re-opened
after the file is released.
However, a proper way to handle this would be to use a lock file,
which is used only for locking and not for storing data at the same
time, as per attached patch




--- globals.py  2011-03-14 16:17:19.466604041 +0100
+++ globals.py_new      2011-03-11 16:55:33.000000000 +0100
@@ -269,10 +269,12 @@
                     response.session_id = None
             if response.session_id:
                 try:
+                    response.session_lock = \
+                        open(response.session_filename+'.lock', 'wb')
+                    portalocker.lock(response.session_lock,
+                            portalocker.LOCK_EX)
                     response.session_file = \
                         open(response.session_filename, 'rb+')
-                    portalocker.lock(response.session_file,
-                            portalocker.LOCK_EX)
                     self.update(cPickle.load(response.session_file))
                     response.session_file.seek(0)
                     oc = response.session_filename.split('/')
[-1].split('-')[0]
@@ -395,21 +397,23 @@
             session_folder =
os.path.dirname(response.session_filename)
             if not os.path.exists(session_folder):
                 os.mkdir(session_folder)
+            response.session_lock = open(response.session_filename
+'.lock', 'wb')
+            portalocker.lock(response.session_lock,
portalocker.LOCK_EX)
             response.session_file = open(response.session_filename,
'wb')
-            portalocker.lock(response.session_file,
portalocker.LOCK_EX)
         if response.session_file:
             cPickle.dump(dict(self), response.session_file)
             response.session_file.truncate()
             try:
-                portalocker.unlock(response.session_file)
+                portalocker.unlock(response.session_lock)
                 response.session_file.close()
+                del response.session_lock
                 del response.session_file
             except: ### this should never happen but happens in
Windows
                 pass

     def _unlock(self, response):
-        if response and response.session_file:
+        if response and response.session_file and
response.session_lock:
             try:
-                portalocker.unlock(response.session_file)
+                portalocker.unlock(response.session_lock)
             except: ### this should never happen but happens in
Windows
                 pass

Reply via email to