I’m trying to make Erlang program that finds prime numbers with processes (ineffective, I know, but hey, it’s just for fun 🙂 ) – something along the lines of numbersimulation.com.
On each “tick” the server spawns new process (“number”) that increments its counter. If counter == that number, it’s a factor, so we let server know. If server doesn’t get any messages, it’s a prime number.
On small numbers (primes upto N, the server(50,L) line) it’s okay, but on the bigger ones it crashes with:
Error in process <0.46.0> with exit value: {badarg,[{primes,number,2,[{file,"primes.erl"},{line,31}]}]}
The line 31 is the server ! hit one – but I don’t understand why it fails. Maybe the line that fails is the one after, number(N,1) ? But why would that fail?
The code:
-module(primes).
-compile(export_all).
main() ->
pg:create(numbers),
Server_PID = spawn(?MODULE,server,[]),
register(server,Server_PID),
ok.
server() -> server(2,[]).
server(50,L) -> io:format("Primes: ~p~n",[L]);
server(N,L) ->
Num_PID = spawn(?MODULE,number,[N]),
pg:join(numbers,Num_PID),
pg:send(numbers,tick),
receive
hit ->
flush(),
server(N+1,L)
after 100 ->
server(N+1,[N|L])
end.
number(N) -> receive {pg_message,_,_,tick} -> number(N,1) end.
number(N,I) ->
receive
{pg_message,_,_,tick} ->
if
N =:= I ->
server ! hit,
number(N,1);
true ->
number(N,I+1)
end
end.
flush() ->
receive _ -> flush()
after 0 -> ok end.
When a registered process dies the name it was registered under is no longer registered. While sending a message to a pid which refers to a dead process is perfectly legal (the message just disappears) sending to an unregistered name is an error, even if the name was once registered.
In your code the
serverprocess does 50 loops spawning a new process and waiting for ahitmessage or timeout. After that theserver/2function ends and theserverprocess dies. When it dies the nameserveris no longer registered so trying to send a message to it generates abadargerror.