I’m following along in the Learn You Some Erlang book and have gotten to the Errors and Processes section where it’s going over monitors, named processes, and restarting processes. At the end it mentions race conditions where you may send messages, the server dies, and you never receive a response. But it kind of just leaves it there.
I may be getting ahead of myself and will find some ways to handle these race conditions further on, but i’m stuck on it.
Here I have a pingpong server that will respond with pong
if it gets a ping
message. It will also exit if it gets a die
message. Both can be configured with timeouts. I also have a monitor that will restart the pingpong server and register it to pingpong_server
if it does die.
-module(pingpong).
-export([start_mon/0]).
-export([ping/0, ping/1, die/0, die/1]).
-export([race/0]).
%% Monitor
start_mon() ->
{Pid, Ref} = spawn_monitor(fun() -> listen() end),
register(pingpong_server, Pid),
receive
%% Restart the pingpong server
{'DOWN', Ref, process, Pid, _} ->
demonitor(Ref),
start_mon()
end.
%% PingPong Server
listen() ->
receive
{From, Ref, ping, T} ->
timer:sleep(T),
From ! {Ref, pong},
listen();
{die, T} ->
timer:sleep(T),
exit(kill)
end.
%% Helpers
die() -> die(0).
die(T) -> pingpong_server ! {die, T}.
ping() -> ping(0).
ping(T) ->
Ref = make_ref(),
pingpong_server ! {self(), Ref, ping, T},
receive
{Ref, pong} ->
io:format("pong~n");
O ->
io:format("got something else ~w~n", [O])
after T + 3000 ->
timeout
end.
race() ->
die(1000),
ping(3000).
Then to use it I spawn the monitor:
Monitor = spawn(fun() -> pingpong:start_mon() end).
And can use the helper functions.
pingpong:ping().
> pong
pingpong:die().
pingpong:ping().
> pong
This all works as expected and the pingpong server will be restarted by the monitor if i kill it. But i created the race function that will send a {die, 1000}
message followed by a {..., ..., ping, 3000}
message so that the pingpong server will die before responding to the ping.
In this situation, is there a mechanism to carry the ping message over to the new procs mailbox or is this something that needs to be handled by the sender?