[Python-checkins] python/dist/src/Lib dumbdbm.py,1.25,1.26

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Sat, 12 Jul 2003 19:22:06 -0700


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

Modified Files:
	dumbdbm.py 
Log Message:
Fixed critical shutdown race in _Database._commit.
Related to SF patch 723231 (which pointed out the problem, but didn't
fix it, just shut up the warning msg -- which was pointing out a dead-
serious bug!).

Bugfix candidate.


Index: dumbdbm.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/dumbdbm.py,v
retrieving revision 1.25
retrieving revision 1.26
diff -C2 -d -r1.25 -r1.26
*** dumbdbm.py	13 Jul 2003 02:05:47 -0000	1.25
--- dumbdbm.py	13 Jul 2003 02:22:03 -0000	1.26
***************
*** 34,37 ****
--- 34,48 ----
  class _Database(UserDict.DictMixin):
  
+     # The on-disk directory and data files can remain in mutually
+     # inconsistent states for an arbitrarily long time (see comments
+     # at the end of __setitem__).  This is only repaired when _commit()
+     # gets called.  One place _commit() gets called is from __del__(),
+     # and if that occurs at program shutdown time, module globals may
+     # already have gotten rebound to None.  Since it's crucial that
+     # _commit() finish sucessfully, we can't ignore shutdown races
+     # here, and _commit() must not reference any globals.
+     _os = _os       # for _commit()
+     _open = _open   # for _commit()
+ 
      def __init__(self, filebasename, mode):
          self._mode = mode
***************
*** 79,93 ****
      # file currently exists, it's deleted.
      def _commit(self):
          try:
!             _os.unlink(self._bakfile)
!         except _os.error:
              pass
  
          try:
!             _os.rename(self._dirfile, self._bakfile)
!         except _os.error:
              pass
  
!         f = _open(self._dirfile, 'w', self._mode)
          for key, pos_and_siz_pair in self._index.iteritems():
              f.write("%r, %r\n" % (key, pos_and_siz_pair))
--- 90,107 ----
      # file currently exists, it's deleted.
      def _commit(self):
+         # CAUTION:  It's vital that _commit() succeed, and _commit() can
+         # be called from __del__().  Therefore we must never reference a
+         # global in this routine.
          try:
!             self._os.unlink(self._bakfile)
!         except self._os.error:
              pass
  
          try:
!             self._os.rename(self._dirfile, self._bakfile)
!         except self._os.error:
              pass
  
!         f = self._open(self._dirfile, 'w', self._mode)
          for key, pos_and_siz_pair in self._index.iteritems():
              f.write("%r, %r\n" % (key, pos_and_siz_pair))