Newbie question can't explain behaviour of my program (tutorial exercise masterslave)

Folkert Hendrix fjmhendrix@REDACTED
Mon Jun 22 14:29:53 CEST 2009


Hi,

I did the tutorial exercise Master Slave
(http://erlang.org/course/exercises.html#ms ) and it does work, but i
can't explain it's behaviour. Is my code wrong?:
this is the output i get:
(erlide@REDACTED)6> masterslave:start(5).
Slave: 5 with Pid: <0.97.0> created
true
Slave: 4 with Pid: <0.98.0> created
Slave: 3 with Pid: <0.99.0> created
(erlide@REDACTED)7> masterslave:to_slave(hello,2).
Slave: 2 with Pid: <0.101.0> created
Slave: 1 with Pid: <0.106.0> created
Slave 2 recieved the message: hello
{message_to_slave,{hello,2}}
(erlide@REDACTED)8> masterslave:to_slave(die,1).
{message_to_slave,{die,1}}
Slave 1 with old PID <0.106.0> restarted with new Pid: <0.108.0>
(erlide@REDACTED)9> masterslave:stop().
Master going downstop
(erlide@REDACTED)10>

Questions:

In the process view of toolbar:start(). I only see 4 slaves created.
When i give the command masterslave:to_slave(hello,2) then the rest of
the slaves are created and can i see the registered master. Slave 2
responds but it wasn't created yet?
When the master stop, the slaves also stop, but i expected the slave
received the exit signal and should write a message.

the code:
%% Author: fh
%% Created: Jun 19, 2009
%% Description: TODO: Add description to masterslave
-module(masterslave).

%%
%% Include files
%%
-include_lib("eunit/include/eunit.hrl").
%%
%% Exported Functions
%%
-export([start/1, stop/0, to_slave/2, init/1, loop_master/1, loop_slave/0]).

%%
%% API Functions
%%

%% Start the master and tell it to start N slave processes.
%% Register the master as the registered process master.
start(N) ->
    register(master, spawn(?MODULE, init, [N]) ).



%%The slave should print all messages it recieves except the message die
loop_slave() ->
    receive
        {master, {say, {Msg, N}}} ->
            io:format("Slave ~w recieved the message: ~w~n",[N, Msg]),
            loop_slave();
        {master, die} ->
            exit("Slave Died");
        {'EXIT', master, _Reason} ->
            io:format("Slave exit normal"),
            exit(normal)
    end.

%%
%% Interface functions
%%


%% Send a message to the master and tell it to relay the message to slave N.
%% The slave should exit (and be restarted by the master) if the message is die.
to_slave(Message, N) ->
    master ! {message_to_slave, {Message, N}}.

stop() ->
    master ! stop.



%%
%% Local Functions
%%

init(N) ->
    process_flag(trap_exit, true),
    init_slave(N, []).


init_slave(0, Slaves) ->
    loop_master(Slaves);

init_slave(N, Slaves) ->
    Pid = spawn_link(?MODULE, loop_slave, []),
    io:format("Slave: ~w with Pid: ~w created~n",[N, Pid]),
    init_slave(N-1,[{N,Pid} | Slaves]).

restart_slave(Pid, Slaves) ->
    {N, OldPid } = lists:keyfind(Pid,2,Slaves),
    NewPid = spawn_link(?MODULE, loop_slave, []),
    io:format("Slave ~w with old PID ~w restarted with new Pid:
~w~n",[N, OldPid, NewPid]),
    lists:keyreplace(Pid, 2, Slaves, {N, NewPid}).


%% return slave N
master_to_slave(Slaves, N, Msg) ->
        case lists:keyfind(N,1,Slaves) of
            false -> io:format("Slave ~w doesn't excist!",[N]);
            {_N, Pid} -> Pid ! {master, Msg}
        end.


%% handle messages from slaves
%% The master should detect the fact that a slave processe died,
%% restart it and print a message that it has done so.
loop_master(Slaves) ->
    receive
        {message_to_slave, {Message, N}} when Message == die ->
            master_to_slave(Slaves,N, die),
            loop_master(Slaves);
        {message_to_slave, {Message, N}} ->
            master_to_slave(Slaves,N, {say, {Message, N}}),
            loop_master(Slaves);
        stop ->
            io:format("Master going down"),
            exit("Master stopped");
        {'EXIT', Pid, Reason} ->
            NewSlaves= restart_slave(Pid, Slaves),
            loop_master(NewSlaves);
        Other ->
             error_logger:error_msg( "Error: Process ~w got unknown
msg ~w~n.", [self(), Other]),
            loop_master(Slaves)
    end.


Regards,
Folkert


More information about the erlang-questions mailing list