Question about transaction usage

Greg Ward greg at gerg.ca
Sun Oct 4 09:20:37 CDT 2009


On Sat, Oct 3, 2009 at 5:36 PM, Matt Mackall <mpm at selenic.com> wrote:
> Unfortunately, destructors in Python are basically useless. If an
> exception is thrown, the traceback object will hold references to every
> stack frame in the call chain, preventing the destructors from getting
> invoked in a timely fashion (and sometimes at all!).
>
> So we make a point of manually destroying locks and transactions.

Got it.  Thanks.

For the benefit of the archive, and anyone else who was confused by
this, I wrote a little script that illustrates the problem:

"""
class C(object):
    def __del__(self):
        print "C destructor called"

def func():
    raise RuntimeError("ow!")

def main():
    c = C()
    try:
        func()
    finally:
        #del c
        pass

try:
    main()
except Exception:
    print "something bad happened"
else:
    print "no exceptions"
"""

If you run it like as-is (no "del c"), the output is

  something bad happened
  C destructor called

which is bad: it means the object doesn't get destroyed until the
script is about to exit.  In a command-line hg, that could probably be
tolerated; it just means the transaction aborts a little later than we
want it to abort.  But it has an arbitrary feel to it, and the
non-locality of the action is unpleasant.

However, uncomment the "del c" line, and the output becomes

  C destructor called
  something bad happened

which is good: it means the object is destroyed from the scope where
it was created.

I think the most useful thing I learned from Java is that you must
never rely on destructors being called: if your object holds
resources, give it an explicit close() method.  (C)Python destructors
are more deterministic than Java destructors, but the rule holds.

Greg


More information about the Mercurial-devel mailing list