spawn without linking?
Dustin Sallings
dustin@REDACTED
Tue Apr 20 21:08:58 CEST 2004
On Apr 20, 2004, at 2:32, Joe Armstrong wrote:
> Things that you want to be independent should not be linked together.
>
> If you have two entirely different applications A and B you absolutely
> do not want A to be linked to B.
>
> If you have some error logger L then you *do* want L to be linked to A
> and L to be linked to B. Errors in A or B should be reported by L.
I suppose I've been thinking about A and B both being launched by M
(like init(8)) so there would always be a process ultimately
responsible for everything.
> spawn_link could *almost* be defined like this:
>
> spawn_link(F) ->
> Pid = spawn(Fun),
> link(Pid),
> Pid.
It was before I found spawn_link! :)
> But this is not correct (Why? - the process might die *between* the
> spawn
> and the link) - so spawn_link does spawn and link atomically.
Definitely good to know.
> If you're new to Erlang I'd use spawn_link - as you build sexier
> applications
> you should think *carefully* about what should happen when things die
> and try to
> stop errors propagating between independent components.
Yeah, I've no doubt a lot to learn.
> You might like to look at the documentation for erlang:monitor (do >
> erl -man man erlang)
> - this sets up a asymmetric link - which is often very useful.
I'm using erlang:monitor for an exercise, but I guess I'm not entirely
sure how to deal with abnormal exits that are propagated by links. For
example, I've got the following code:
% Demo process
echo() ->
receive
{From, N} ->
io:format("Sending back ~p from ~p\n", [N, self()]),
From ! N,
echo();
stop ->
io:format("Stopping ~p\n", [self()]),
true;
error ->
exit("Got an error");
Unknown ->
error_logger:error_msg("~p exiting due to unhandled
message: ~p\n",
[self(), Unknown])
end.
% Replace a process in a process list
mcpReplaceProcess(OldPid, Procs) ->
NewProc = spawn_link(coursemp, echo, []),
% erlang:monitor(process, NewProc),
io:format("Created new proc ~p\n", [NewProc]),
OtherProcs = lists:filter(fun (P) -> not(P == OldPid) end, Procs),
[NewProc | OtherProcs].
% Listen for messages from the processes this thing controls
mcpLoop(Procs) ->
io:format("Looping with procs: ~p\n", [Procs]),
receive
{sendto, N, Msg} ->
lists:nth(N, Procs) ! Msg,
mcpLoop(Procs);
{'DOWN', _Ref, process, Pid, _Flag} ->
io:format("MCP got down message for ~p\n", [Pid]),
mcpLoop(mcpReplaceProcess(Pid, Procs));
Msg ->
io:format("MCP got ~p\n", [Msg]),
mcpLoop(Procs)
end.
% Start up a bunch of processes and loop
mcpMonitor(N) ->
Procs = listBuilder(fun () -> spawn_link(coursemp, echo, []) end,
N, []),
lists:foreach(fun (P) -> erlang:monitor(process, P) end, Procs),
mcpLoop(Procs).
% Get an Mcp process controlling the given number of echo processes
mcp(N) ->
spawn_link(coursemp, mcpMonitor, [N]).
I'd like the 'error' message to be handled properly by the echo
process in a similar fashion to what monitor is doing, but it seems to
have different behavior:
1> Mcp = coursemp:mcp(5).
Looping with procs: [<0.36.0>,<0.35.0>,<0.34.0>,<0.33.0>,<0.32.0>]
<0.31.0>
2> Mcp ! {sendto, 3, echo}.
Looping with procs: [<0.36.0>,<0.35.0>,<0.34.0>,<0.33.0>,<0.32.0>]
{sendto,3,echo}
=ERROR REPORT==== 20-Apr-2004::12:03:40 ===
<0.34.0> exiting due to unhandled message: echo
MCP got down message for <0.34.0>
Created new proc <0.39.0>
Looping with procs: [<0.39.0>,<0.36.0>,<0.35.0>,<0.33.0>,<0.32.0>]
3> Mcp ! {sendto, 3, {Mcp, echo}}.
Looping with procs: [<0.39.0>,<0.36.0>,<0.35.0>,<0.33.0>,<0.32.0>]
{sendto,3,{<0.31.0>,echo}}
Sending back echo from <0.35.0>
MCP got echo
Looping with procs: [<0.39.0>,<0.36.0>,<0.35.0>,<0.33.0>,<0.32.0>]
4> Mcp ! {sendto, 3, stop}.
Looping with procs: [<0.39.0>,<0.36.0>,<0.35.0>,<0.33.0>,<0.32.0>]
{sendto,3,stop}
Stopping <0.35.0>
MCP got down message for <0.35.0>
Created new proc <0.42.0>
Looping with procs: [<0.42.0>,<0.39.0>,<0.36.0>,<0.33.0>,<0.32.0>]
5> Mcp ! {sendto, 3, die}.
Looping with procs: [<0.42.0>,<0.39.0>,<0.36.0>,<0.33.0>,<0.32.0>]
{sendto,3,die}
=ERROR REPORT==== 20-Apr-2004::12:04:04 ===
<0.36.0> exiting due to unhandled message: die
MCP got down message for <0.36.0>
Created new proc <0.44.0>
Looping with procs: [<0.44.0>,<0.42.0>,<0.39.0>,<0.33.0>,<0.32.0>]
6> Mcp ! {sendto, 3, error}.
Looping with procs: [<0.44.0>,<0.42.0>,<0.39.0>,<0.33.0>,<0.32.0>]
{sendto,3,error}
** exited: "Got an error" **
7> Mcp ! {sendto, 3, die}.
{sendto,3,die}
As of the 'error' message, the Mcp has died. Does this mean the Mcp
should *not* be linked to the processes it controls, or is there a
different way to handle the errors?
Thanks for your help. Erlang may prove to be pretty useful in my line
of work.
--
Dustin Sallings
More information about the erlang-questions
mailing list