jodal / pykka

🌀 Pykka makes it easier to build concurrent Python applications.

Home Page:https://pykka.readthedocs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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 have True as the result if the actor was stopped successfully, and False 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.