[pypy-svn] r50824 - in pypy/dist/pypy: interpreter module/__builtin__ module/_file module/_socket module/_weakref
arigo at codespeak.net
arigo at codespeak.net
Mon Jan 21 13:10:13 CET 2008
Author: arigo
Date: Mon Jan 21 13:10:12 2008
New Revision: 50824
Modified:
pypy/dist/pypy/interpreter/baseobjspace.py
pypy/dist/pypy/interpreter/typedef.py
pypy/dist/pypy/module/__builtin__/interp_classobj.py
pypy/dist/pypy/module/_file/interp_file.py
pypy/dist/pypy/module/_socket/interp_socket.py
pypy/dist/pypy/module/_weakref/interp__weakref.py
Log:
Add logic for built-in objects to make sure that all the weakrefs to
them are cleared before the rest of their __del__ methods run.
This showed up in pypy-c-boehm runs of
lib-python/modified-2.4.1/test/test_file.py,
where a weakref to a file could sometimes still
be alive after the file was closed by its __del__.
Modified: pypy/dist/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/baseobjspace.py (original)
+++ pypy/dist/pypy/interpreter/baseobjspace.py Mon Jan 21 13:10:12 2008
@@ -117,6 +117,23 @@
raise OperationError(space.w_TypeError, space.wrap(
"cannot create weak reference to '%s' object" % typename))
+ def clear_all_weakrefs(self):
+ """Call this at the beginning of interp-level __del__() methods
+ in subclasses. It ensures that weakrefs (if any) are cleared
+ before the object is further destroyed.
+ """
+ lifeline = self.getweakref()
+ if lifeline is not None:
+ # Clear all weakrefs to this object before we proceed with
+ # the destruction of the object. We detach the lifeline
+ # first: if the code following before_del() calls the
+ # app-level, e.g. a user-defined __del__(), and this code
+ # tries to use weakrefs again, it won't reuse the broken
+ # (already-cleared) weakrefs from this lifeline.
+ self.setweakref(lifeline.space, None)
+ lifeline.clear_all_weakrefs()
+
+
class Wrappable(W_Root):
"""A subclass of Wrappable is an internal, interpreter-level class
that can nevertheless be exposed at application-level by space.wrap()."""
Modified: pypy/dist/pypy/interpreter/typedef.py
==============================================================================
--- pypy/dist/pypy/interpreter/typedef.py (original)
+++ pypy/dist/pypy/interpreter/typedef.py Mon Jan 21 13:10:12 2008
@@ -149,15 +149,7 @@
parent_destructor = getattr(cls, '__del__', None)
class Proto(object):
def __del__(self):
- lifeline = self.getweakref()
- if lifeline is not None:
- # Clear all weakrefs to this object before we call
- # the app-level __del__. We detach the lifeline
- # first: if the app-level __del__ tries to use
- # weakrefs again, they won't reuse the broken
- # (already-cleared) ones from this lifeline.
- self.setweakref(self.space, None)
- lifeline.clear_all_weakrefs()
+ self.clear_all_weakrefs()
try:
self.space.userdel(self)
except OperationError, e:
@@ -546,6 +538,12 @@
weakref_descr.name = '__weakref__'
def make_weakref_descr(cls):
+ """Make instances of the Wrappable subclass 'cls' weakrefable.
+ This returns the '__weakref__' desctriptor to use for the TypeDef.
+ Note that if the class also defines a custom '__del__', the
+ __del__ should call self.clear_all_weakrefs() before it clears
+ the resources used by the object.
+ """
# force the interface into the given cls
def getweakref(self):
return self._lifeline_
Modified: pypy/dist/pypy/module/__builtin__/interp_classobj.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/interp_classobj.py (original)
+++ pypy/dist/pypy/module/__builtin__/interp_classobj.py Mon Jan 21 13:10:12 2008
@@ -694,19 +694,8 @@
)
class W_InstanceObjectWithDel(W_InstanceObject):
- # XXX this is code duplication from pypy.interpreter.typedef
- # find a way to prevent this.
def __del__(self):
-
- lifeline = self.getweakref()
- if lifeline is not None:
- # Clear all weakrefs to this object before we call
- # the app-level __del__. We detach the lifeline
- # first: if the app-level __del__ tries to use
- # weakrefs again, they won't reuse the broken
- # (already-cleared) ones from this lifeline.
- self.setweakref(self.space, None)
- lifeline.clear_all_weakrefs()
+ self.clear_all_weakrefs()
try:
self.descr_del()
except OperationError, e:
Modified: pypy/dist/pypy/module/_file/interp_file.py
==============================================================================
--- pypy/dist/pypy/module/_file/interp_file.py (original)
+++ pypy/dist/pypy/module/_file/interp_file.py Mon Jan 21 13:10:12 2008
@@ -33,6 +33,7 @@
def __del__(self):
# assume that the file and stream objects are only visible in the
# thread that runs __del__, so no race condition should be possible
+ self.clear_all_weakrefs()
self.direct_close()
def fdopenstream(self, stream, fd, mode, name):
Modified: pypy/dist/pypy/module/_socket/interp_socket.py
==============================================================================
--- pypy/dist/pypy/module/_socket/interp_socket.py (original)
+++ pypy/dist/pypy/module/_socket/interp_socket.py Mon Jan 21 13:10:12 2008
@@ -22,6 +22,10 @@
return space.str_w(w_obj)
class W_RSocket(Wrappable, RSocket):
+ def __del__(self):
+ self.clear_all_weakrefs()
+ self.close()
+
def accept_w(self, space):
"""accept() -> (socket object, address info)
Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py
==============================================================================
--- pypy/dist/pypy/module/_weakref/interp__weakref.py (original)
+++ pypy/dist/pypy/module/_weakref/interp__weakref.py Mon Jan 21 13:10:12 2008
@@ -8,7 +8,8 @@
class WeakrefLifeline(object):
- def __init__(self):
+ def __init__(self, space):
+ self.space = space # this is here for W_Root.clear_all_weakrefs()
self.refs_weak = []
self.cached_weakref_index = -1
self.cached_proxy_index = -1
@@ -145,7 +146,7 @@
def descr__new__weakref(space, w_subtype, w_obj, w_callable=None):
lifeline = w_obj.getweakref()
if lifeline is None:
- lifeline = WeakrefLifeline()
+ lifeline = WeakrefLifeline(space)
w_obj.setweakref(space, lifeline)
return lifeline.get_or_make_weakref(space, w_subtype, w_obj, w_callable)
@@ -218,7 +219,7 @@
is about to be finalized."""
lifeline = w_obj.getweakref()
if lifeline is None:
- lifeline = WeakrefLifeline()
+ lifeline = WeakrefLifeline(space)
w_obj.setweakref(space, lifeline)
return lifeline.get_or_make_proxy(space, w_obj, w_callable)
More information about the Pypy-commit
mailing list