Open randomPoison opened 4 years ago
As of #11 being merged, it's now possible to send a message without awaiting a response. This makes it possible to at least fix a deadlock once discovered, though deadlocks are still possible to cause in the manner described above.
It's currently very easy to deadlock two actors that send each other messages. For example:
In this case when
Bar::tell_foo
callsFoo::tell_me
, both actors will deadlock. This is is because theFoo
actor is waiting forFoo::tell_bar
to complete before it can process another message, butFoo::tell_bar
is waiting onFoo::tell_me
to complete. Sincetell_me
won't be processed untiltell_bar
finishes, neither actor can progress and so both deadlock.In this specific case, the issue is that we have no way to enqueue a message for an actor without also waiting for the actor to respond to this message. If we had a "fire and forget" option for enqueuing a message without waiting for the response,
tell_foo
could send thetell_me
message toFoo
without waiting for the message to be processed, thereby avoiding the deadlock.However, at a more fundamental level, the fact that messages can return results will always introduce the possibility of a deadlock. The only way to fully prevent deadlocks would be to have enqueuing a message always be a synchronous action that either succeeds immediately or fails due to the message queue being full (or the actor having stopped).
I'd like to make thespian as deadlock-free as possible. It may not be possible to completely prevent all deadlocks, but the API should push users to usage patterns that avoid deadlocks by default. I'm going to have to do some research into how deadlocks are handled in other actor frameworks like Actix and what mechanisms can be used to prevent/avoid them.