diff --git a/rpyc/core/netref.py b/rpyc/core/netref.py index 4c2acc8d..9c009741 100644 --- a/rpyc/core/netref.py +++ b/rpyc/core/netref.py @@ -10,7 +10,7 @@ _local_netref_attrs = frozenset([ - '____conn__', '____oid__', '__class__', '__cmp__', '__del__', '__delattr__', + '____conn__', '____oid__', '____refcount__', '__class__', '__cmp__', '__del__', '__delattr__', '__dir__', '__doc__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__slots__', '__str__', @@ -43,6 +43,7 @@ _builtin_types.extend([ bytes, bytearray, type(iter(range(10))), memoryview, ]) + xrange = range else: _builtin_types.extend([ basestring, unicode, long, xrange, type(iter(xrange(10))), file, @@ -116,13 +117,15 @@ class BaseNetref(object): """ # this is okay with py3k -- see below __metaclass__ = NetrefMetaclass - __slots__ = ["____conn__", "____oid__", "__weakref__"] + __slots__ = ["____conn__", "____oid__", "__weakref__", "____refcount__"] def __init__(self, conn, oid): self.____conn__ = conn self.____oid__ = oid + self.____refcount__ = 1 + def __del__(self): try: - asyncreq(self, consts.HANDLE_DEL) + asyncreq(self, consts.HANDLE_DEL, self.____refcount__) except Exception: # raised in a destructor, most likely on program termination, # when the connection might have already been closed. diff --git a/rpyc/core/protocol.py b/rpyc/core/protocol.py index 4a4445f0..d71a3619 100644 --- a/rpyc/core/protocol.py +++ b/rpyc/core/protocol.py @@ -315,7 +315,11 @@ def _unbox(self, package): if label == consts.LABEL_REMOTE_REF: oid, clsname, modname = value if oid in self._proxy_cache: - return self._proxy_cache[oid] + proxy = self._proxy_cache[oid] + proxy.____refcount__ += 1 # other side increased refcount on boxing, + # if I'm returning from cache instead of new object, + # must increase refcount to match + return proxy proxy = self._netref_factory(oid, clsname, modname) self._proxy_cache[oid] = proxy return proxy @@ -600,7 +604,7 @@ def _handle_close(self): self._cleanup() def _handle_getroot(self): return self._local_root - def _handle_del(self, oid): + def _handle_del(self, oid, count=1): self._local_objects.decref(oid) def _handle_repr(self, oid): return repr(self._local_objects[oid]) diff --git a/rpyc/lib/colls.py b/rpyc/lib/colls.py index 5e946a7a..13018620 100644 --- a/rpyc/lib/colls.py +++ b/rpyc/lib/colls.py @@ -73,13 +73,13 @@ def add(self, obj): def clear(self): with self._lock: self._dict.clear() - def decref(self, key): + def decref(self, key, count=1): with self._lock: slot = self._dict[key] - if slot[1] < 1: + if slot[1] < count: del self._dict[key] else: - slot[1] -= 1 + slot[1] -= count self._dict[key] = slot def __getitem__(self, key): with self._lock: