Killing and restarting processes I am a beginner with Erlang and currently making my way through the awesome Joe Armstrong's book. The following are my answers to exercises 5 and 6 for the concurrency chapter. The code can probably be much better but at least it seems to work fine after some tests. I'm just happy to be able to understand this language, I'm def having to re-learn how to think about my programming logic, and I think that's a good thing.

5) Write a function that starts and monitors several worker processes. If any of the worker processes dies abnormally, restart it.

ex5_start(FList) -&gt;
    spawn(fun() -&gt;
        [bring_back(F) || F &lt;- FList]
        end).

bring_back(FID) -&gt;
    spawn(fun() -&gt;
        {Pid, Ref} = spawn_monitor(FID),
            io:format("Pid = ~p~n",[Pid]),
            receive
                {'DOWN', Ref, process, Pid, normal} -&gt; void;
                {'DOWN', Ref, process, Pid, _Why} -&gt; bring_back(FID)
            after infinity -&gt; void
            end
        end).


6) Write a function that starts and monitors several worker processes. If any of the worker processes dies abnormally, kill all the worker processes and restart them all.

ex6_start(Flist) when is_list(Flist) -&gt;
    Size = length(Flist),
    spawn(fun() -&gt;
            {Pid,Ref} = spawn_monitor(fun() -&gt; 
                                        start_and_monitor(Size,Flist), 
                                        receive 
                                        after infinity -&gt; true 
                                        end 
                                    end),
            receive
                {'DOWN',Ref,process,Pid,_} -&gt; io:format("All dead. Restarting.~n") ,
                ex6_start(Flist) 
            end
        end).


start_and_monitor(1,Flist) -&gt;
    Fun = lists:nth(1,Flist),
    Pid = spawn_link(Fun),
    io:format("Pid ~p created.~n",[Pid]);
start_and_monitor(N,Flist) -&gt;
    Fun = lists:nth(N,Flist),
    Pid = spawn_link(Fun),
    io:format("Pid ~p created.~n",[Pid]),
    start_and_monitor(N-1,Flist).
For the first problem:

You are using more processes than strictly needed, since you


spawn a process A that
spawns a number of monitoring processes M that each
spawn a worker W and monitoring it.


If a worker fails, you spawn a new monitor 'M' and a new worker.

ex5_start(FList) -&gt;
    spawn(fun() -&gt; %% This is the spawn of process A
        [bring_back(F) || F &lt;- FList] %% This is the list for B's
        end).

bring_back(FID) -&gt;
    spawn(fun() -&gt; %% This is the spawning of an M
        {Pid, Ref} = spawn_monitor(FID), %% This is the spawning of a W
            io:format("Pid = ~p~n",[Pid]),
            receive
                {'DOWN', Ref, process, Pid, normal} -&gt; void;
                {'DOWN', Ref, process, Pid, _Why} -&gt;
                    %% New M and W
                    bring_back(FID) 
            after infinity -&gt; void %% you can skip this entire line
            end
        end).


An after clause with a hardcoded infinity timeout is never going to be executed, so you can skip it.

You can think of a simpler solution, where you spawn_monitor the workers and associate their FIDs with a Pid and Ref (e.g. in a list comprehension) and then have a second phase in which whenever a DOWN message arrives you lookup the relevant worker PID and restart its FID. You don't even need a separate A process.



For the second problem:

Several things seem off:


You are using an intermediate process on which all others are linked
This intermediate process will block on this piece of code:

                                receive 
                                after infinity -&gt; true 
                                end

you are not killing all processes on an error, just linking them all to die together with the intermediate process. This may not be what is needed, if e.g. some process is trapping exit signals.
If all processes exit normally, the intermediate process will remain blocked forever.


If you follow my suggestion for the previous question, it is easy to replace the second phase with a different one that does the correct thing (remember to also keep track of processes that have died normally).