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

anthonybaxter@sourceforge.net anthonybaxter@sourceforge.net
Mon, 22 Apr 2002 18:55:31 -0700


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

Modified Files:
      Tag: release21-maint
	Queue.py 
Log Message:
backport mhammond's patch:

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

Original patch(es):
python/dist/src/Lib/Queue.py:1.15



Index: Queue.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/Queue.py,v
retrieving revision 1.14
retrieving revision 1.14.4.1
diff -C2 -d -r1.14 -r1.14.4.1
*** Queue.py	18 Feb 2001 03:30:53 -0000	1.14
--- Queue.py	23 Apr 2002 01:55:29 -0000	1.14.4.1
***************
*** 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