[Twisted-Python] Unjellying and circular references?

Glyph glyph at twistedmatrix.com
Sat Dec 26 13:57:33 MST 2020


Out official bug tracker is at https://twistedmatrix.com/trac/newticket — if you could file it there it would be great.  (Github login required.)

Thanks!

> On Dec 16, 2020, at 2:21 AM, Jasper Phillips <jasperisjaded at gmail.com> wrote:
> 
> 
> 
> 
>> On Fri, Dec 11, 2020 at 6:08 AM Jean-Paul Calderone <exarkun at twistedmatrix.com> wrote:
>>> On Fri, Dec 11, 2020 at 8:19 AM Jasper Phillips <jasperisjaded at gmail.com> wrote:
>> 
>>> I'm using perspective broker to transfer objects in a networked game, which I'm having trouble unjellying -- the remote versions wind up with dangling twisted.persisted.crefutil._Dereference instances, so don't match the original objects.
>>> 
>>> I'm seeing this for objects that have circular references to each other. I've refactored things to mostly avoid circular references and sidestep this, but have one remaining case where I find circular references mean clearer code that I'm reluctant to refactor.
>>> 
>>> Is there some trick I'm missing to avoid _Dereferences?
>> 
>> No, it's supposed to Just Work™ so you've found a bug in some part of the implementation.  If you can produce a minimal reproducing example then it may be worth a bug report.  But after that, I'd suggest investigating HTTP or AMP as a replacement for PB.
> 
> Here's a test case demonstrating the bug:
> 
> import sys
> from twisted.persisted.crefutil import _Dereference
> from twisted.spread             import pb, jelly
> 
> class RemoteCopyable( pb.Copyable, pb.RemoteCopy ):  pass
> jelly.globalSecurity.allowInstancesOf( RemoteCopyable )
> pb.setCopierForClassTree( sys.modules[__name__], pb.Copyable )
> 
> if __name__ == '__main__':
>     # circular object ref
>     cell           = RemoteCopyable()
>     cell.link      = RemoteCopyable()
>     cell.link.cell = cell
> 
>     # Mimic sending across network
>     broker         = pb.Broker()
>     serializedCell = broker.serialize( cell )
>     remoteCell     = broker.unserialize( serializedCell )
> 
>     print( _Dereference is type(remoteCell.link.cell) )
> 
> This bug stems from twisted.spread.flavors.RemoteCopy.setCopyableState(), which works fine for Python 2! But the UTF fix for Python 3 broke circular references. It looks like this:
> 
> def setCopyableState(self, state):
>     if _PY3:
>         state = {x.decode('utf8') if isinstance(x, bytes)
>                  else x:y for x,y in state.items()}
>     self.__dict__ = state
> 
> Here is a simple tweak that fixes the problem:
> 
> def setCopyableState(self, state):
>     if _PY3:
>         for x, y in list(state.items()):
>             if isinstance(x, bytes):
>                 del state[x]
>                 state[x.decode('utf8')] = y
>     self.__dict__ = state
> 
> 
> Basically the reference unwinding that takes place in twisted.spread.jelly._Unjellier._unjelly_reference()'s call to ref.resolveDependants() relies upon setCopyableStates()'s passed in state being used directly, such that all matching references' __dict__ point to the same object.
> 
> Hope this helps clarify. Is there some more formal location than this list that you'd like a bug report filed?
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20201226/fef651fc/attachment.htm>


More information about the Twisted-Python mailing list