[pypy-svn] r78002 - in pypy/branch/leak-finder/pypy: rlib rpython/lltypesystem rpython/memory/test

arigo at codespeak.net arigo at codespeak.net
Fri Oct 15 18:35:46 CEST 2010


Author: arigo
Date: Fri Oct 15 18:35:43 2010
New Revision: 78002

Modified:
   pypy/branch/leak-finder/pypy/rlib/rgc.py
   pypy/branch/leak-finder/pypy/rpython/lltypesystem/rffi.py
   pypy/branch/leak-finder/pypy/rpython/memory/test/test_gc.py
Log:
Test and fix for *a real leak*!  Yay :-)


Modified: pypy/branch/leak-finder/pypy/rlib/rgc.py
==============================================================================
--- pypy/branch/leak-finder/pypy/rlib/rgc.py	(original)
+++ pypy/branch/leak-finder/pypy/rlib/rgc.py	Fri Oct 15 18:35:43 2010
@@ -170,7 +170,14 @@
         return hop.genop('gc_set_max_heap_size', [v_nbytes],
                          resulttype=lltype.Void)
 
-def can_move(p):    # NB. must not be called with NULL pointers
+def can_move(p):
+    """Check if the GC object 'p' is at an address that can move.
+    Must not be called with None.  With non-moving GCs, it is always False.
+    With some moving GCs like the SemiSpace GC, it is always True.
+    With other moving GCs like the MiniMark GC, it can be True for some
+    time, then False for the same object, when we are sure that it won't
+    move any more.
+    """
     return True
 
 class CanMoveEntry(ExtRegistryEntry):

Modified: pypy/branch/leak-finder/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/branch/leak-finder/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/branch/leak-finder/pypy/rpython/lltypesystem/rffi.py	Fri Oct 15 18:35:43 2010
@@ -644,7 +644,14 @@
         """
         Either free a non-moving buffer or keep the original storage alive.
         """
-        if rgc.can_move(data):
+        # We cannot rely on rgc.can_move(data) here, because its result
+        # might have changed since get_nonmovingbuffer().  Instead we check
+        # if 'buf' points inside 'data'.  This is only possible if we
+        # followed the 2nd case in get_nonmovingbuffer(); in the first case,
+        # 'buf' points to its own raw-malloced memory.
+        data_start = cast_ptr_to_adr(llstrtype(data)) + \
+            offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0)
+        if buf != cast(TYPEP, data_start):
             lltype.free(buf, flavor='raw')
         else:
             keepalive_until_here(data)

Modified: pypy/branch/leak-finder/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/branch/leak-finder/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/branch/leak-finder/pypy/rpython/memory/test/test_gc.py	Fri Oct 15 18:35:43 2010
@@ -368,6 +368,14 @@
         res = self.interpret(f, [4, 42])
         assert res == 12
 
+    def test_print_leak(self):
+        def f(n):
+            for i in range(n):
+                print i
+            return 42
+        res = self.interpret(f, [10])
+        assert res == 42
+
     def test_weakref_across_minor_collection(self):
         import weakref
         class A:



More information about the Pypy-commit mailing list