[pypy-commit] pypy default: Tighten the checks.

arigo noreply at buildbot.pypy.org
Tue Sep 13 10:58:00 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r47241:d462a721df1b
Date: 2011-09-12 22:22 +0200
http://bitbucket.org/pypy/pypy/changeset/d462a721df1b/

Log:	Tighten the checks.

diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -43,16 +43,27 @@
             raise getmemoryerror(self.space)
 
     def switch(self, w_to):
+        sthread = self.sthread
+        if sthread is None:
+            start_state.clear()
+            raise geterror(self.space, "continulet not initialized yet")
+        if sthread.is_empty_handle(self.h):
+            start_state.clear()
+            raise geterror(self.space, "continulet already finished")
         to = self.space.interp_w(W_Continulet, w_to, can_be_None=True)
         if to is not None:
-            if to.sthread is None:
+            if to.sthread is not sthread:
                 start_state.clear()
-                raise geterror(self.space, "continulet not initialized yet")
+                if to.sthread is None:
+                    msg = "continulet not initialized yet"
+                else:
+                    msg = "cross-thread double switch"
+                raise geterror(self.space, msg)
             if self is to:    # double-switch to myself: no-op
                 return get_result()
-        if self.sthread is None:
-            start_state.clear()
-            raise geterror(self.space, "continulet not initialized yet")
+            if sthread.is_empty_handle(to.h):
+                start_state.clear()
+                raise geterror(self.space, "continulet already finished")
         ec = self.check_sthread()
         #
         start_state.origin = self
@@ -63,14 +74,8 @@
             # double switch: the final destination is to.h
             start_state.destination = to
         #
-        h = start_state.destination.h
-        sthread = self.sthread
-        if sthread.is_empty_handle(h):
-            start_state.clear()
-            raise geterror(self.space, "continulet already finished")
-        #
         try:
-            do_switch(sthread, h)
+            do_switch(sthread, start_state.destination.h)
         except MemoryError:
             start_state.clear()
             raise getmemoryerror(self.space)
diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py
--- a/pypy/module/_continuation/test/test_stacklet.py
+++ b/pypy/module/_continuation/test/test_stacklet.py
@@ -643,6 +643,16 @@
             assert res == "done"
         main()
 
+    def test_bug_finish_with_already_finished_stacklet(self):
+        from _continuation import continulet, error
+        # make an already-finished continulet
+        c1 = continulet(lambda x: x)
+        c1.switch()
+        # make another continulet
+        c2 = continulet(lambda x: x)
+        # this switch is forbidden, because it causes a crash when c2 finishes
+        raises(error, c1.switch, to=c2)
+
     def test_various_depths(self):
         skip("may fail on top of CPython")
         # run it from test_translated, but not while being actually translated


More information about the pypy-commit mailing list