[pypy-commit] pypy default: (issue2545, issue2530, possibly others)

arigo pypy.commits at gmail.com
Mon Apr 24 13:30:58 EDT 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r91122:b2569cf1bd55
Date: 2017-04-24 19:19 +0200
http://bitbucket.org/pypy/pypy/changeset/b2569cf1bd55/

Log:	(issue2545, issue2530, possibly others)

	Fix a multithreading bug that was there since a while with
	shadowstack. Thanks matti for a lot of the work around these issues.

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
@@ -75,6 +75,7 @@
         BaseRootWalker.__init__(self, gctransformer)
         # NB. 'self' is frozen, but we can use self.gcdata to store state
         gcdata = self.gcdata
+        gcdata.can_look_at_partial_stack = True
 
         def incr_stack(n):
             top = gcdata.root_stack_top
@@ -109,7 +110,19 @@
         BaseRootWalker.setup_root_walker(self)
 
     def walk_stack_roots(self, collect_stack_root, is_minor=False):
+        # Note that if we're the first minor collection after a thread
+        # switch, then we also need to disable the 'is_minor'
+        # optimization.  The reason is subtle: we need to walk the whole
+        # stack because otherwise, we can be in the middle of an
+        # incremental major collection, and the new stack was just moved
+        # off a ShadowStackRef object (gctransform/shadowstack.py) which
+        # was not seen yet.  We might completely miss some old objects
+        # from the parts of that stack that are skipped by this is_minor
+        # optimization.
         gcdata = self.gcdata
+        if is_minor and not gcdata.can_look_at_partial_stack:
+            is_minor = False
+            gcdata.can_look_at_partial_stack = True
         walk_stack_root(self.invoke_collect_stack_root, collect_stack_root,
                         None, gcdata.root_stack_base, gcdata.root_stack_top,
                         is_minor=is_minor)
@@ -298,6 +311,7 @@
                   "restore_state_from: broken shadowstack")
         self.gcdata.root_stack_base = shadowstackref.base
         self.gcdata.root_stack_top  = shadowstackref.top
+        self.gcdata.can_look_at_partial_stack = False
         self._cleanup(shadowstackref)
 
     def start_fresh_new_state(self):


More information about the pypy-commit mailing list