Skip to content

Commit b78ce94

Browse files
committed
fix: Break reference cycle between Actor and ActorRef
Actor and ActorRef both had references to each other, creating a cycle that blocked instant memory freeing since the actor's reference count never reached zero. This changes the ActorRef reference to the actor to use a weakref, so that the ActorRef doesn't contribute to the Actor's reference count, enabling instant freeing of the memory. Fixes #249, #250
1 parent 4168837 commit b78ce94

File tree

2 files changed

+6
-2
lines changed

2 files changed

+6
-2
lines changed

src/pykka/_proxy.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,11 @@ def __init__(
138138
if not actor_ref.is_alive():
139139
msg = f"{actor_ref} not found"
140140
raise ActorDeadError(msg)
141+
if (actor := actor_ref._actor_weakref()) is None: # noqa: SLF001
142+
msg = f"{actor_ref}'s actor weakref has been deallocated"
143+
raise ActorDeadError(msg)
141144
self.actor_ref = actor_ref
142-
self._actor = actor_ref._actor # noqa: SLF001
145+
self._actor = actor
143146
self._attr_path = attr_path or ()
144147
self._known_attrs = introspect_attrs(root=self._actor, proxy=self)
145148
self._actor_proxies = {}

src/pykka/_ref.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import weakref
34
from typing import (
45
TYPE_CHECKING,
56
Any,
@@ -51,7 +52,7 @@ def __init__(
5152
self,
5253
actor: A,
5354
) -> None:
54-
self._actor = actor
55+
self._actor_weakref = weakref.ref(actor)
5556
self.actor_class = actor.__class__
5657
self.actor_urn = actor.actor_urn
5758
self.actor_inbox = actor.actor_inbox

0 commit comments

Comments
 (0)