[Checkins] SVN: zc.twist/trunk/src/zc/twist/ Fix an issue where attempting to pickle zc.twist.Failure objects could result in a RunTimeError.

Patrick Strawderman patrick at zope.com
Tue Sep 29 16:34:55 EDT 2009


Log message for revision 104626:
  Fix an issue where attempting to pickle zc.twist.Failure objects could result in a RunTimeError.

Changed:
  U   zc.twist/trunk/src/zc/twist/README.txt
  U   zc.twist/trunk/src/zc/twist/__init__.py

-=-
Modified: zc.twist/trunk/src/zc/twist/README.txt
===================================================================
--- zc.twist/trunk/src/zc/twist/README.txt	2009-09-29 20:07:52 UTC (rev 104625)
+++ zc.twist/trunk/src/zc/twist/README.txt	2009-09-29 20:34:54 UTC (rev 104626)
@@ -788,6 +788,25 @@
     *--- End of Failure #... ---
     <BLANKLINE>
 
+    In some cases, it is possible that a Failure object may include references
+    to itself, for example, indirectly through a zc.async job whose result
+    is a Failure.  Failure's __getstate__ method used to use deepcopy, which
+    in cases like this could result in infinite recursion.
+
+    >>> import zc.twist
+    >>> class Kaboom(Exception):
+    ...     pass
+    >>> class Foo(object):
+    ...     failure = None
+    ...     def fail(self):
+    ...         raise Kaboom, self
+    >>> foo = Foo()
+    >>> try:
+    ...     foo.fail()
+    ... except Kaboom:
+    ...     foo.failure = zc.twist.Failure()
+    >>> ignored = foo.failure.__getstate__() # used to cause RunTimeError.
+
 .. [#teardown_monkeypatch]
 
     >>> twisted.internet.reactor.callLater = oldCallLater

Modified: zc.twist/trunk/src/zc/twist/__init__.py
===================================================================
--- zc.twist/trunk/src/zc/twist/__init__.py	2009-09-29 20:07:52 UTC (rev 104625)
+++ zc.twist/trunk/src/zc/twist/__init__.py	2009-09-29 20:34:54 UTC (rev 104626)
@@ -1,4 +1,4 @@
-import copy, random, types, warnings
+import random, types, warnings
 
 import ZODB.interfaces
 import ZODB.POSException
@@ -130,9 +130,8 @@
         pass # already done
 
     def __getstate__(self):
-        res = self.__dict__
+        res = self.__dict__.copy()
         if not self.sanitized:
-            res = copy.deepcopy(res)
             res['stack'] = []
             res['frames'] = [
                 [



More information about the checkins mailing list