Changeset 12:5eadb64fa613

Show
Ignore:
Timestamp:
05/15/05 00:33:02 (3 years ago)
Author:
Allan Saddi <allan@saddi.com>
branch:
default
convert_revision:
svn:46762da8-4eb7-0310-94e9-d918b60927c8/flup/trunk@1783
Message:

Prevent possible deadlock related to DiskSessionStore? locking.
Add logic to SessionStore? so that it will block if attempting to
check out a Session that's already been checked out.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • ChangeLog

    r11 r12  
     12005-05-15  Allan Saddi  <asaddi@ganymede.saddi.net> 
     2 
     3        * Prevent possible deadlock related to DiskSessionStore locking. 
     4        * Add logic to SessionStore so that it will block if attempting to 
     5          check out a Session that's already been checked out. 
     6 
    172005-05-14  Allan Saddi  <asaddi@ganymede.saddi.net> 
    28 
  • flup/middleware/session.py

    r11 r12  
    3838 
    3939try: 
    40     import thread 
     40    import threading 
    4141except ImportError: 
    42     import dummy_thread as thread 
     42    import dummy_threading as threading 
    4343 
    4444__all__ = ['Session', 
     
    142142 
    143143    def __init__(self, timeout=60, sessionClass=None): 
    144         self._lock = thread.allocate_lock() 
     144        self._lock = threading.Condition() 
    145145 
    146146        # Timeout in minutes 
     
    201201        self._lock.acquire() 
    202202        try: 
     203            # If we know it's already checked out, block. 
     204            while identifier in self._checkOutList: 
     205                self._lock.wait() 
    203206            sess = self._loadSession(identifier) 
    204207            if sess is not None: 
     
    234237                self._deleteSession(session.identifier) 
    235238            del self._checkOutList[session.identifier] 
     239            self._lock.notify() 
    236240        finally: 
    237241            self._lock.release() 
     
    410414 
    411415    def _lockSession(self, identifier, block=True): 
    412         fn = self._filenameForSession(identifier) + '.lock' 
    413         while True: 
    414             try: 
    415                 fd = os.open(fn, os.O_WRONLY|os.O_CREAT|os.O_EXCL) 
    416             except OSError, e: 
    417                 if e.errno != errno.EEXIST: 
    418                     raise 
    419             else: 
    420                 os.close(fd) 
    421                 break 
    422  
    423             if not block: 
    424                 return False 
    425  
    426             # See if the lock is stale. If so, remove it. 
    427             try: 
    428                 now = time.time() 
    429                 mtime = os.path.getmtime(fn) 
    430                 if (mtime + 60) < now: 
    431                     os.unlink(fn) 
    432             except OSError, e: 
    433                 if e.errno != errno.ENOENT: 
    434                     raise 
    435  
    436             time.sleep(0.1) 
    437  
    438         return True 
     416        # Release SessionStore lock so we don't deadlock. 
     417        self._lock.release() 
     418        try: 
     419            fn = self._filenameForSession(identifier) + '.lock' 
     420            while True: 
     421                try: 
     422                    fd = os.open(fn, os.O_WRONLY|os.O_CREAT|os.O_EXCL) 
     423                except OSError, e: 
     424                    if e.errno != errno.EEXIST: 
     425                        raise 
     426                else: 
     427                    os.close(fd) 
     428                    break 
     429 
     430                if not block: 
     431                    return False 
     432 
     433                # See if the lock is stale. If so, remove it. 
     434                try: 
     435                    now = time.time() 
     436                    mtime = os.path.getmtime(fn) 
     437                    if (mtime + 60) < now: 
     438                        os.unlink(fn) 
     439                except OSError, e: 
     440                    if e.errno != errno.ENOENT: 
     441                        raise 
     442 
     443                time.sleep(0.1) 
     444 
     445            return True 
     446        finally: 
     447            self._lock.acquire() 
    439448 
    440449    def _unlockSession(self, identifier):