[Python-checkins] python/dist/src/Lib Queue.py,1.14,1.15

mhammond@sourceforge.net mhammond@sourceforge.net
Thu, 18 Apr 2002 17:11:37 -0700


Update of /cvsroot/python/python/dist/src/Lib
In directory usw-pr-cvs1:/tmp/cvs-serv3478

Modified Files:
	Queue.py 
Log Message:
Fix bug 544473 - "Queue module can deadlock".
Use try/finally to ensure all Queue locks remain stable.
Includes test case.  Bugfix candidate.


Index: Queue.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/Queue.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -d -r1.14 -r1.15
*** Queue.py	18 Feb 2001 03:30:53 -0000	1.14
--- Queue.py	19 Apr 2002 00:11:31 -0000	1.15
***************
*** 56,66 ****
              raise Full
          self.mutex.acquire()
!         was_empty = self._empty()
!         self._put(item)
!         if was_empty:
!             self.esema.release()
!         if not self._full():
!             self.fsema.release()
!         self.mutex.release()
  
      def put_nowait(self, item):
--- 56,77 ----
              raise Full
          self.mutex.acquire()
!         release_fsema = True
!         try:
!             was_empty = self._empty()
!             self._put(item)
!             # If we fail before here, the empty state has
!             # not changed, so we can skip the release of esema
!             if was_empty:
!                 self.esema.release()
!             # If we fail before here, the queue can not be full, so
!             # release_full_sema remains True
!             release_fsema = not self._full()
!         finally:
!             # Catching system level exceptions here (RecursionDepth,
!             # OutOfMemory, etc) - so do as little as possible in terms
!             # of Python calls.
!             if release_fsema:
!                 self.fsema.release()
!             self.mutex.release()
  
      def put_nowait(self, item):
***************
*** 85,95 ****
              raise Empty
          self.mutex.acquire()
!         was_full = self._full()
!         item = self._get()
!         if was_full:
!             self.fsema.release()
!         if not self._empty():
!             self.esema.release()
!         self.mutex.release()
          return item
  
--- 96,114 ----
              raise Empty
          self.mutex.acquire()
!         release_esema = True
!         try:
!             was_full = self._full()
!             item = self._get()
!             # If we fail before here, the full state has
!             # not changed, so we can skip the release of fsema
!             if was_full:
!                 self.fsema.release()
!             # Failure means empty state also unchanged - release_esema
!             # remains True.
!             release_esema = not self._empty()
!         finally:
!             if release_esema:
!                 self.esema.release()
!             self.mutex.release()
          return item