[issue1695] Ignored exception in mercurial.util.atomictempfile

Adrian Buehlmann mercurial-bugs at selenic.com
Fri Jun 12 16:28:56 UTC 2009


New submission from Adrian Buehlmann <adrian at cadifra.com>:

d19ab9a56bf4 contains a bug in mercurial.util.atomictempfile:

class atomictempfile(object):
    """file-like object that atomically updates a file

    All writes will be redirected to a temporary copy of the original
    file.  When rename is called, the copy is renamed to the original
    name, making the changes visible.
    """
    def __init__(self, name, mode, createmode):
        self.__name = name
        self._fp = None
        self.temp = mktempcopy(name, emptyok=('w' in mode),
                               createmode=createmode)
        self._fp = posixfile(self.temp, mode)

    def __getattr__(self, name):
        return getattr(self._fp, name)

    def rename(self):
        if not self.closed:
            self._fp.close()
            rename(self.temp, localpath(self.__name))

    def __del__(self):
        if not self.closed:
            try:
                os.unlink(self.temp)
            except: pass
            if self._fp:
                self._fp.close()

                
if __init__ fails in mktempcopy (for example due to an OSError thrown),
__del__ is called with self._fp set to None.

The line

        if not self.closed:

leads to a call of getattr(self._fp, 'closed') with self._fp being None.

This gives an error like:

Exception exceptions.AttributeError: "'NoneType' object has no attribute
'closed'" in
<bound method atomictempfile.__del__ of <mercurial.util.atomictempfile object at
0x00CCF370>> ignored


Proposed fix by tonfa: http://paste.lisp.org/display/81765

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -767,17 +767,18 @@
         return getattr(self._fp, name)
 
     def rename(self):
-        if not self.closed:
+        if not self._fp.closed:
             self._fp.close()
             rename(self.temp, localpath(self.__name))
 
     def __del__(self):
-        if not self.closed:
+        if not self._fp:
+            return
+        if not self._fp.closed:
             try:
                 os.unlink(self.temp)
             except: pass
-            if self._fp:
-                self._fp.close()
+            self._fp.close()
 
 def makedirs(name, mode=None):
     """recursive directory creation with parent mode inheritance"""

----------
messages: 9499
nosy: abuehl
priority: bug
status: unread
title: Ignored exception in mercurial.util.atomictempfile

____________________________________________________
Mercurial issue tracker <mercurial-bugs at selenic.com>
<http://www.selenic.com/mercurial/bts/issue1695>
____________________________________________________



More information about the Mercurial-devel mailing list