[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))