[pypy-commit] pypy stm: Propagate the exception that occurs in a transaction.

arigo noreply at buildbot.pypy.org
Fri Jan 20 18:01:54 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: stm
Changeset: r51558:b4fd35482b14
Date: 2012-01-20 18:01 +0100
http://bitbucket.org/pypy/pypy/changeset/b4fd35482b14/

Log:	Propagate the exception that occurs in a transaction.

diff --git a/pypy/module/transaction/interp_transaction.py b/pypy/module/transaction/interp_transaction.py
--- a/pypy/module/transaction/interp_transaction.py
+++ b/pypy/module/transaction/interp_transaction.py
@@ -89,9 +89,13 @@
 
     @staticmethod
     def _run_in_transaction(pending):
-        space = state.space
-        space.call_args(pending.w_callback, pending.args)
-        # xxx exceptions?
+        if state.got_exception is not None:
+            return   # return early if there is already a 'got_exception'
+        try:
+            space = state.space
+            space.call_args(pending.w_callback, pending.args)
+        except Exception, e:
+            state.got_exception = e
 
 
 def add(space, w_callback, __args__):
@@ -159,6 +163,7 @@
     state.num_waiting_threads = 0
     state.finished = False
     state.running = True
+    state.got_exception = None
     #
     for i in range(state.num_threads):
         threadintf.start_new_thread(_run_thread, ())
@@ -170,3 +175,9 @@
     assert state.pending_lists.keys() == [state.main_thread_id]
     assert not state.is_locked_no_tasks_pending()
     state.running = False
+    #
+    # now re-raise the exception that we got in a transaction
+    if state.got_exception is not None:
+        e = state.got_exception
+        state.got_exception = None
+        raise e
diff --git a/pypy/module/transaction/test/test_transaction.py b/pypy/module/transaction/test/test_transaction.py
--- a/pypy/module/transaction/test/test_transaction.py
+++ b/pypy/module/transaction/test/test_transaction.py
@@ -41,3 +41,21 @@
             for index in range(7):
                 assert lst[start + index] == lst[start] + index
         assert seen == set([10, 20, 30])
+
+    def test_propagate_exception(self):
+        import transaction, time
+        lst = []
+        def f(n):
+            lst.append(n)
+            time.sleep(0.5)
+            raise ValueError(n)
+        transaction.add(f, 10)
+        transaction.add(f, 20)
+        transaction.add(f, 30)
+        try:
+            transaction.run()
+            assert 0, "should have raised ValueError"
+        except ValueError, e:
+            pass
+        assert len(lst) == 1
+        assert lst[0] == e.args[0]


More information about the pypy-commit mailing list