Actor doesn't stop
rand0x0m opened this issue · comments
Calling ActorRef.stop() inside Actor (or ThreadingActor) extender class doesn't stop the actor (maybe it's some kind of deadlock?)
import pykka
from pykka.registry import ActorRegistry
class TestActor(pykka.ThreadingActor):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def on_failure(self, exception_type, exception_value, traceback):
print("Failed lol!")
def on_receive(self, message):
return None
def on_start(self):
ref = ActorRegistry.get_by_urn(self.actor_urn)
if ref is not None:
ref.stop(block=True)
print("Exploited")
def on_stop(self):
print("Stopping!")
if __name__ == "__main__":
ta = TestActor.start()
Yes, this is a deadlock. Because on_start()
is blocking (waiting for ref.stop(block=True)
the message sent by ref.stop()
is never processed, and on_start()
blocks forever.
An actor have two ways to stop itself:
self.stop()
adds a stop message to the end of the inbox and returns nothing.self.actor_ref.stop(block=False)
does the same and returns a future that will haveTrue
as the result if the actor was stopped successfully, andFalse
otherwise.
Of course, making on_start()
block waiting for the future's result will reintroduce the same issue. on_start()
must finish for any messages to be processed.