diff --git a/lib/locking.py b/lib/locking.py
index 25a8bf19b5a59bcb63672eff4d9e66665326c869..7ead1ca149e4de1a31420abd82be5f696498fa0b 100644
--- a/lib/locking.py
+++ b/lib/locking.py
@@ -55,6 +55,7 @@ class SharedLock:
     # lock waiters
     self.__nwait_exc = 0
     self.__nwait_shr = 0
+    self.__npass_shr = 0
 
     # is this lock in the deleted state?
     self.__deleted = False
@@ -133,6 +134,8 @@ class SharedLock:
     finally:
       self.__nwait_exc -= 1
 
+    assert self.__npass_shr == 0, "SharedLock: internal fairness violation"
+
   def acquire(self, blocking=1, shared=0):
     """Acquire a shared lock.
 
@@ -154,25 +157,35 @@ class SharedLock:
 
       # We cannot acquire the lock if we already have it
       assert not self.__is_owned(), "double acquire() on a non-recursive lock"
+      assert self.__npass_shr >= 0, "Internal fairness condition weirdness"
 
       if shared:
         self.__nwait_shr += 1
         try:
+          wait = False
           # If there is an exclusive holder waiting we have to wait.  We'll
           # only do this once, though, when we start waiting for the lock. Then
           # we'll just wait while there are no exclusive holders.
           if self.__nwait_exc > 0:
             # TODO: if !blocking...
+            wait = True
             self.__wait(self.__turn_shr)
 
           while self.__exc is not None:
+            wait = True
             # TODO: if !blocking...
             self.__wait(self.__turn_shr)
 
           self.__shr.add(threading.currentThread())
+
+          # If we were waiting note that we passed
+          if wait:
+            self.__npass_shr -= 1
+
         finally:
           self.__nwait_shr -= 1
 
+        assert self.__npass_shr >= 0, "Internal fairness condition weirdness"
       else:
         # TODO: if !blocking...
         # (or modify __exclusive_acquire for non-blocking mode)
@@ -192,6 +205,7 @@ class SharedLock:
     """
     self.__lock.acquire()
     try:
+      assert self.__npass_shr >= 0, "Internal fairness condition weirdness"
       # Autodetect release type
       if self.__is_exclusive():
         self.__exc = None
@@ -200,6 +214,8 @@ class SharedLock:
         # mode if there are shared holders waiting. Otherwise wake up the next
         # exclusive holder.
         if self.__nwait_shr > 0:
+          # Make sure at least the ones which were blocked pass.
+          self.__npass_shr = self.__nwait_shr
           self.__turn_shr.notifyAll()
         elif self.__nwait_exc > 0:
          self.__turn_exc.notify()
@@ -207,9 +223,18 @@ class SharedLock:
       elif self.__is_sharer():
         self.__shr.remove(threading.currentThread())
 
-        # If there are no more shared holders and some exclusive holders are
-        # waiting let's wake one up.
-        if len(self.__shr) == 0 and self.__nwait_exc > 0:
+        # If there are shared holders waiting (and not just scheduled to pass)
+        # there *must* be an exclusive holder waiting as well; otherwise what
+        # were they waiting for?
+        assert (self.__nwait_exc > 0 or self.__npass_shr > 0 or
+                self.__nwait_shr == 0), \
+               "Lock sharers waiting while no exclusive is queueing"
+
+        # If there are no more shared holders either in or scheduled to pass,
+        # and some exclusive holders are waiting let's wake one up.
+        if (len(self.__shr) == 0 and
+            self.__nwait_exc > 0 and
+            not self.__npass_shr > 0):
           self.__turn_exc.notify()
 
       else: