[pypy-commit] pypy cpyext-gc-cycle: Fixed issue during forking with rrc cycle detection

stevie_92 pypy.commits at gmail.com
Fri Jun 14 03:25:33 EDT 2019


Author: Stefan Beyer <home at sbeyer.at>
Branch: cpyext-gc-cycle
Changeset: r96804:d4f961b90303
Date: 2019-06-14 09:24 +0200
http://bitbucket.org/pypy/pypy/changeset/d4f961b90303/

Log:	Fixed issue during forking with rrc cycle detection Fixed issue with
	non-rc rrc objects

diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -3151,6 +3151,7 @@
             self.rrc_finalizer_type = finalizer_type
             self.rrc_clear_weakref_callback = clear_weakref_callback
             self.rrc_enabled = True
+            self.rrc_cycle_enabled = True
             self.rrc_state = self.RAWREFCOUNT_STATE_DEFAULT
 
     def check_no_more_rawrefcount_state(self):
@@ -3164,6 +3165,12 @@
         self.rrc_p_dict.foreach(check_value_is_null, None)
         self.rrc_p_dict_nurs.foreach(check_value_is_null, None)
 
+    def deactivate_rawrefcount_cycle(self):
+        self.rrc_cycle_enabled = False
+
+    def activate_rawrefcount_cycle(self):
+        self.rrc_cycle_enabled = True
+
     def rawrefcount_create_link_pypy(self, gcobj, pyobject):
         ll_assert(self.rrc_enabled, "rawrefcount.init not called")
         obj = llmemory.cast_ptr_to_adr(gcobj)
@@ -3405,10 +3412,13 @@
     _rrc_free._always_inline_ = True
 
     def rrc_major_collection_trace(self):
-        self._rrc_debug_check_consistency(print_label="begin-mark")
+        if not self.rrc_cycle_enabled:
+            self._rrc_debug_check_consistency(print_label="begin-mark")
+
         # Only trace and mark rawrefcounted object if we are not doing
         # something special, like building gc.garbage.
-        if self.rrc_state == self.RAWREFCOUNT_STATE_DEFAULT:
+        if (self.rrc_state == self.RAWREFCOUNT_STATE_DEFAULT and
+                self.rrc_cycle_enabled):
             merged_old_list = False
             # check objects with finalizers from last collection cycle
             if not self._rrc_gc_list_is_empty(self.rrc_pyobj_old_list):
@@ -3477,6 +3487,30 @@
             self.objects_to_trace.append(obj)
             self.visit_all_objects()
 
+    def _rrc_major_trace_nongc(self, pyobject, ignore):
+        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
+        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT
+        #
+        pyobj = self._pyobj(pyobject)
+        pygchdr = self.rrc_pyobj_as_gc(pyobj)
+        if pygchdr != lltype.nullptr(self.PYOBJ_GC_HDR):
+            if pygchdr.c_gc_refs != self.RAWREFCOUNT_REFS_UNTRACKED:
+                rc = 0
+            else:
+                rc = pyobj.c_ob_refcnt
+        else:
+            rc = pyobj.c_ob_refcnt
+
+        if rc == REFCNT_FROM_PYPY or rc == REFCNT_FROM_PYPY_LIGHT or rc == 0:
+            pass  # the corresponding object may die
+        else:
+            # force the corresponding object to be alive
+            debug_print("pyobj stays alive", pyobj, "rc", rc)
+            intobj = pyobj.c_ob_pypy_link
+            obj = llmemory.cast_int_to_adr(intobj)
+            self.objects_to_trace.append(obj)
+            self.visit_all_objects()
+
     def rrc_major_collection_free(self):
         if self.rrc_state == self.RAWREFCOUNT_STATE_DEFAULT:
             if not self._rrc_gc_list_is_empty(self.rrc_pyobj_old_list):
@@ -3572,6 +3606,10 @@
             self._rrc_pyobj_gc_refcnt_set(pygchdr, refcnt)
             pygchdr = pygchdr.c_gc_next
 
+        # For all non-gc pyobjects which have a refcount > 0,
+        # mark all reachable objects on the pypy side
+        self.rrc_p_list_old.foreach(self._rrc_major_trace_nongc, None)
+
         # For every object in this set, if it is marked, add 1 as a real
         # refcount (p_list => pyobj stays alive if obj stays alive).
         self.rrc_p_list_old.foreach(self._rrc_obj_fix_refcnt, None)
diff --git a/rpython/memory/gctransform/shadowstack.py b/rpython/memory/gctransform/shadowstack.py
--- a/rpython/memory/gctransform/shadowstack.py
+++ b/rpython/memory/gctransform/shadowstack.py
@@ -187,6 +187,7 @@
 
         def switch_shadow_stacks(new_tid):
             # we have the wrong shadowstack right now, but it should not matter
+            gcdata.gc.deactivate_rawrefcount_cycle()
             thread_stacks = gcdata.thread_stacks
             try:
                 if thread_stacks is None:
@@ -210,6 +211,7 @@
                 shadow_stack_pool.start_fresh_new_state()
             # done
             #
+            gcdata.gc.activate_rawrefcount_cycle()
             gcdata.active_tid = new_tid
         switch_shadow_stacks._dont_inline_ = True
 


More information about the pypy-commit mailing list