Erlang print PID as results - erlang

Here is my code:
-module(cooperate).
-compile(export_all).
producer(_Pid, 0) ->
done;
producer(Pid, N) ->
io:format("process ~p producing ~p~n", [Pid, rand:uniform(N)]),
producer(Pid, N-1).
start() ->
spawn(cooperate, producer, [rand:uniform(7), 7]).
Results:
{ok,cooperate}
2> cooperate:start().
process 2 producing 6
<0.88.0>
process 2 producing 3
process 2 producing 4
process 2 producing 4
process 2 producing 1
process 2 producing 2
process 2 producing 1
3>
Expecting:
process <0.88.0> producing 6
process <0.88.0> producing 3
process <0.88.0> producing 4
process <0.88.0> producing 4
process <0.88.0> producing 1
process <0.88.0> producing 2
process <0.88.0> producing 1
What should I do if I want to print <0.88.0> between process and producing instead of 2?
I tried something like pid_to_list, ~p, etc

The first argument of your producer function is named Pid, yet you never pass any pid as the first argument of this function. The argumenr when the function is first called is rand:uniform(7), which in your test happen to return 2.
If you want your function to print the pid of the process you spawned, the best way would be to get rid of the first argument, and use self() instead.

Related

When is a process restarted in Erlang supervision?

Can you give some examples where a process gets restarted by Erlang supervisor. If a process dies, it will restart. But how does a process die?
Thanks.
You can take as example what occurs in the Erlang shell, for example consider the sequence:
1> self().
<0.32.0>
2> A = 1.
1
3> self().
<0.32.0>
4> A = 2.
** exception error: no match of right hand side value 2
5> self().
<0.37.0>
1> The first command asks to the shell to prompt its own Pid: <0.32.0>.
2> Next a new command set the variable A to 1, it works, since A was unbound.
3> A new request to the shell shows that its Pid didn't change.
4> trying to match A with the integer 2 fails, it raise an exception. In fact, in the background, the shell process dies, and a supervisor restart it immediately.
5> It can be verified with a new request to get the shell Pid, now it is <0.37.0>.
6> when the shell died, it has lost every information, and it is restarted from scratch. But during initialization it can connect to some other processes who was in charge of keeping the history of the session, and all the bound variables. It can be verified by asking the value of A:
6> A.
1
7> or by asking the history
7> h().
1: self()
-> <0.32.0>
2: A = 1
-> 1
3: self()
-> <0.32.0>
4: A = 2
-> {'EXIT',{{badmatch,2},[{erl_eval,expr,3,[]}]}}
5: self()
-> <0.37.0>
6: A
Depending on the environment (hardware failure, loss of communication, bad parameters, bug...) an erlang process may die with an Error reason. If it is managed in a supervision tree (or your own monitoring) it can be restarted from scratch. It is the application responsibility to provide the means to all the processes to recover the appropriate state.
An erlang process may also die with the reason "normal", for example when a user close a session (in the shell you type q().), in this case, the supervisor will not restart it.
You will find many valuable information on the web:
design principle
erlang.org supervisor
learn you some erlang : run time errors
learn you some erlang : errors and processes
learn you some erlang : supervisors

Erlang receive after 0

Say I have an Erlang process whose message queue currently looks like this:
msg1
msg2
{timeout, Ref1, some_atom}
msg3
msg4
What the message queue will look like if I do:
receive
{timeout, Ref1, some_atom} ->
0
after 0
false
end
You can try this in the shell to find out:
1> Pid = spawn(fun F() -> receive start -> receive {timeout, Ref1, some_atom} -> F() after 0 -> ok end end end).
<0.47.0>
2> Pid ! msg1.
msg1
3> Pid ! msg2.
msg2
4> Pid ! {timeout, erlang:make_ref(), some_atom}.
{timeout,#Ref<0.0.8.133>,some_atom}
5> Pid ! msg3.
msg3
6> Pid ! msg4.
msg4
7> erlang:process_info(Pid, messages).
{messages,[msg1,msg2,
{timeout,#Ref<0.0.8.133>,some_atom},
msg3,msg4]}
8> Pid ! start.
start
9> erlang:process_info(Pid, messages).
{messages,[msg1,msg2,msg3,msg4]}
Command 1 creates a process Pid waiting to receive a start atom, after which it performs the receive you specified in your question.
Commands 2-6 create the message queue in Pid matching your question.
Command 7 verifies that the Pid message queue is what we expect.
Command 8 sends the start atom to cause Pid to execute the receive you specified in your question, and then go back and wait for another start message.
Command 9 checks the Pid message queue again. As we can see, the code received the {timeout, Ref1, some_atom} tuple and left msg1 and similar atoms in the queue.
The results of command 9 are exactly what we expect, due to Erlang's selective receive capability, which causes it to look through the message queue to find the first match when receiving messages. If no messages matched in this case, the after 0 clause would instead execute, which in this code would mean the spawned function would finish and Pid would exit.

Erlang server request order

I'm trying to understand request order in erlang, but I can't seem to grasp it very well. Here's the example code:
test() ->
Server = start(),
spawn(fun() -> write(Server, 2),
io:format(”Child 1 read ~p~n”, [read(Server)]) end),
write(Server, 3),
write2(Server, 5),
spawn(fun() -> write2(Server, 1),
io:format(”Child 2 read ~p~n”, [read(Server)]) end),
io:format(”Parent read ~p~n”, [read(Server)]).
And here's the server:
start() ->
spawn(fun() -> init() end).
init() -> loop(0).
loop(N) ->
receive
{read, Pid} ->
Pid ! {value, self(), N},
loop(N);
{write, Pid, M} ->
Pid ! {write_reply, self()},
loop(M);
{write2, _Pid, M} -> loop(M)
end.
read(Serv) ->
Serv ! {read, self()},
receive {value, Serv, N} -> N end.
write(Serv, N) ->
Serv ! {write, self(), N},
receive {write_reply, Serv} -> ok end.
write2(Serv, N) ->
Serv ! {write2, self(), N},
ok.
I understand that different values could be printed by the three different processes created in test/0, but I'm trying to figure out the lowest and highest values that could be printed by those Parent, Child1 and Child2 processes. The answer states:
Parent: lowest 1, highest 5
Child1: lowest 1, highest 5
Child2: lowest 1, highest 2
Can somebody explain this?
Keep in mind that Erlang guarantees message order only from one process to another. If process A sequentially sends message 1 and then message 2 to process B, then B will receive them in that order. But Erlang guarantees no specific ordering of messages arriving at B if multiple concurrent processes are sending them. In this example, Parent, Child1, and Child2 all run concurrently and all send messages concurrently to Server.
The Parent process performs the following sequential steps:
Spawns the Server process. This eventually sets the initial value in the Server loop to 0.
Spawns Child1. This eventually writes the value 2 to Server, then reads from Server and prints the result.
Uses write/2 to send the value 3 to Server. The write case in the loop/1 function first replies to the caller and then installs the value 3 for its next iteration.
Uses write2/2 to send 5 to Server. The write2/2 function just sends a message to Server and does not await a reply. The write2 case in the loop/1 function just installs the value 5 for its next iteration.
Spawns Child2, which eventually calls write2/2 with the value 1, and then reads Server and prints the result.
Reads Server and prints the result.
For Parent, step 3 sends the value 3 to Server, so as far as Parent is concerned, Server now has the value 3. In step 4, Parent calls write2/2 to send 5 to the server, and that message must arrive at Server sometime after the message sent in step 3. In step 6, Parent performs a read, but all we know is that this message has to arrive at Server after the write message in step 4. This message ordering means the highest value Parent can see is 5.
The lowest value Parent can see is 1 because if Child2 gets its write message of 1 to Server after the Parent write message of 5 but before the final Parent read message, then Parent will see the 1.
For Child1, the highest value it can see is 5 because it runs concurrently with Parent and the two messages sent by Parent could arrive at Server before its write message of 2. The lowest Child1 can see is 1 because the Child2 write message of 1 can arrive before the Child1 read message.
For Child2, the lowest value it can see is its own write of 1. The highest value it can see is 2 from the write of Child1 because the Parent writes of 3 and 5 occur before Child2 is spawned, thus Child1 is the only process writing concurrently and so only it has a chance of interleaving its write message between the Child2 write and read messages.

Erlang Code understanding

Hi I am doing some Erlang training by understanding some basic Erlang server modules. However I am getting stuck on this one. In this module I am supposed to tell the lowest and highest possible values that can be printed by each of the 3 processes (parent and 2 child processes) because depending on particular order of execution, different values may get printed by the 3 processes.
I executed the test and got 2 for Parent, 3 for both of the child processes but I don't know how they got those values. Can someone specifically explain the process to me? Appreciated.
Here is the module:
-module(p4).
-export([start/0, init/0, read/1, incr/1, reset/1, test/0]).
start()->
spawn(fun() -> init() end).
init() -> loop(0).
loop(N) ->
receive
{read, Pid} ->
Pid ! {value, self(), N},
loop(N);
{incr, Pid} ->
Pid ! {incr_reply, self()},
loop(N+1);
{reset, Pid} ->
Pid ! {reset_reply, self()},
loop(0)
end.
read(Serv) ->
Serv ! {read, self()},
receive {value, Serv, N} -> N end.
incr(Serv)->
Serv ! {incr, self()},
receive{incr_reply, Serv} -> ok end.
reset(Serv) ->
Serv ! {reset, self()},
receive {reset_reply, Serv} -> ok end.
test() ->
Server = start(),
spawn(fun() -> incr(Server),
io:format("Child 1 read ~p~n", [read(Server)]) end),
incr(Server),
spawn(fun() -> incr(Server),
io:format("child 2 read ~p~n", [read(Server)]) end),
io:format("Parent read ~p~n", [read(Server)]).
One precision to understand Lukasz's answer is that all Server interfaces (read,incr, reset) are synchronous: they wait for an answer from the server. This means that the process which uses these interfaces cannot do anything until the Server completes the request. It is very important to justify that child2 cannot read less than 2.
2 sequence diagrams to visualize the processes:
Try to print any message server is receiving (or use debugger tracing) for better understanding and you should get something like:
Server state was: 0 and received: {incr,<0.59.0>}
Server state was: 1 and received: {incr,<0.109.0>}
Server state was: 2 and received: {read,<0.59.0>}
Server state was: 2 and received: {incr,<0.110.0>}
Parent read 2
Server state was: 3 and received: {read,<0.109.0>}
Server state was: 3 and received: {read,<0.110.0>}
Child 1 read 3
child 2 read 3
<0.59.0> is parent process, <0.109.0> is child 1 and <0.110.0> is child 2.
It means that parent read message was delivered before read of children processes but after first child incr. But it doesn't have to be like this. It depends on process scheduling. The only guarantee you have is that messages sent from process A to process B will be delivered in the same order.
Due to synchronous nature of incr(Server) and read(Server) it doesn't really matter. Because each of these processes runs incr(Server) before read(Server) it must get at least 1 but note that child 2 was spawned after parent executed incr(Server) which is synchronous operation so it must be at least 1 when it runs its own incr(Server), so when it reads it must be at least 2. The maximum value for each of them is 3 (overall number of incr(Server) and means that any read(Server) of each of them may be delayed).
Summary of possible printed values: Parent: 1,2,3; Child 1: 1,2,3; Child 2: 2,3
Simplified execution order of:
your case (parent gets 2 and both children get 3):
parent: spawn server
parent: spawn child 1
parent: incr(Server)
child 1: incr(Server)
parent: spawn child 2
parent: io:format("parent read ~p~n",[read(Server)]) % prints 2
child 2: incr(Server)
child 1: parent: io:format("child 1 read ~p~n",[read(Server)]) % prints 3
child 2: parent: io:format("child 2 read ~p~n",[read(Server)]) % prints 3
minimum case for child 1:
parent: spawn server
parent: spawn child 1
child 1: incr(Server)
child 1: io:format("child 1 read ~p~n",[read(Server)]) % prints 1
...
maximum case for parent:
parent: spawn server
parent: spawn child 1
parent: incr(Server)
parent: spawned child 2
child 1: incr(Server)
child 2: incr(Server)
Parent: io:format("child 1 read ~p~n",[read(Server)]) % prints 3
...
I've created massive test which spawned 100000 processes which run test/0 simultaneously and created external stat_server which gets and counts every process read(Server) resault and here it is:
[{{child1,1},2}, % child 1 reads 1 only twice. Sometimes it's 1 sometimes it's 0, it varies
{{child1,2},53629},
{{child1,3},46369},
{{child2,2},107},
{{child2,3},99893},
{{parent,1},855},
{{parent,2},99112},
{{parent,3},33}]

Erlang/ets: reset ets table after getting a "bad argument"?

I've been learning how to use ets, but one thing that has bothered me is that, occasionally*, ets:match throws a bad argument… And, from them on, all subsequent calls (even calls which previously worked) also throw a bad argument:
> ets:match(Tid, { [$r | '$1'] }, 1).
% this match works...
% Then, at some point, this comes up:
** exception error: bad argument
in function ets:match/3
called as ets:match(24589,{[114|'$1']},1)
% And from then on, matches stop working:
> ets:match(Tid, { [$r | '$1'] }, 1).
** exception error: bad argument
in function ets:match/3
called as ets:match(24589,{[114|'$1']},1)
Is there any way to "reset" the ets system so that I can query it (ie, from the shell) again?
*: I haven't been able to reproduce the problem… But it happens fairly often while I'm trying to do "other things".
Although I'm not 100% sure, this thread seems to answer your question. It appears that you're observing this behaviour in the shell. If so, two facts are interacting in a confusing way:
An ets table is deleted as soon as its owning process dies.
The erlang shell dies whenver it receives an exception and is silently restarted.
So, when you get the first exception, the current shell process dies causing the ets table to be deleted, and then a new shell process is started for you. Now, when you try another ets:match, it fails because the table no longer exists.
Dale already told you what happens. You can confirm that by calling self() in the shell every now and then.
As a quick workaround you can spawn another process to create a public table for you. Then that table won't die along with your shell.
1> self().
<0.32.0> % shell's Pid
2> spawn(fun() -> ets:new(my_table, [named_table, public]), receive X -> ok end end).
<0.35.0> % the spawned process's Pid
3> ets:insert(my_table, {a, b}).
true
Now make an exception and check that the table indeed survived.
4> 1/0.
** exception error: bad argument in an arithmetic expression
in operator '/'/2
called as 1 / 0
5> self().
<0.38.0> % shell's reborn, with a different Pid
6> ets:insert(my_table, {c, d}).
true
7> ets:tab2list(my_table).
[{c,d},{a,b}] % table did survive the shell restart
To delete the table, just send something to your spawned process:
8> pid(0,35,0) ! bye_bye.
bye_bye
9> ets:info(my_table).
undefined

Resources