[erlang-questions] Pid after node restart

Tony Rogvall tony@REDACTED
Tue Sep 30 10:11:36 CEST 2014


The magic is called creation :-)

You can check the creation number in a node by calling:

erlang:system_info(creation).

This number is either 1,2 or 3 in current implementation, and its purpose is to be able to make
sure that code can tell new pids from old ones, as you discovered.

The nodes creation number is handed out by the epmd (Erlang port mapper daemon) when
a node starts:

> erl -sname n1
> erlang:system_info(creation).
1
> halt().

> erl -sname n1
> erlang:system_info(creation).
2
> halt().

> erl -sname n1
> erlang:system_info(creation).
3
> halt().

> erl -sname n1
> erlang:system_info(creation).
1
> halt().

The creation is not stored together with the pid it self, but stored in a distribution entry that is populated
and transfered with the distribution protocol. 
It is a bit strange (to say the least) the the print names of the two pids are identical but they totally different.

The ert_debug:size reveal that one is a "local" pid and the other one is a "remote".
Transferring the pids to P1 and P2 and run:

> erts_debug:size(P1). 
4
> erts_debug:size(P2).
0

Meaning that P2 is the local pid and P1 is the "remote"/old pid.

The only (non-supported) way I found to print this info is an obscure (but nice) function called 

erts_debug:get_internal_state(node_and_dist_references).

But before this can be called this function must be called first:

erts_debug:set_internal_state(available_internal_state, true).

The data in my case looks like:

> erts_debug:get_internal_state(node_and_dist_references).      
{{node_references,[{{n1@REDACTED,2},
                    1,
                    [{{system,undefined},[{system,1}]}]},
                   {{n2@REDACTED,3},
                    12,
                    [{{process,<0.13.0>},[{heap,11}]},
                     {{process,<0.14.0>},[{heap,1}]}]},
                   {{n1@REDACTED,1},
                    7,
                    [{{process,<0.32.0>},[{heap,4}]},
                     {{process,<0.41.0>},[{heap,2}]},
                     {{process,<0.77.0>},[{heap,1}]}]}]},
 {dist_references,[{n2@REDACTED,2,
                           [{{port,#Port<0.2237>},[{control,1}]},
                            {{node,{n2@REDACTED,3}},[{node,1}]}]},
                   {n1@REDACTED,3,
                           [{{process,<0.20.0>},[{control,1}]},
                            {{node,{n1@REDACTED,1}},[{node,1}]},
                            {{node,{n1@REDACTED,2}},[{node,1}]}]}]}}

You can see the {n1@REDACTED,1}, {n1@REDACTED,2} in the node_reference part of the list.
Do not ask about the other number, you have to read the source code :-)

/Tony

On 29 sep 2014, at 11:14, Pavel Baturko <pabftk@REDACTED> wrote:

> Hi,
> 
> I have a question about internal structure of pid and possibility to compare pids in distributed system.
> I see strange (for me) behavior of erlang (version 17.1) and I need help to explain this.
> My case is:
> I have 2 connected nodes.
> 	• On node 1 I generate a pid P (<0.X.0>)
> 	• P is transfered to node 2 (on node 2 I receive it as <Y.X.0>)
> 	• P is transfered back from node 2 to node 1 (I'm receiving it as P2)
> 	• P2 is recognized as local pid (<0.X.0>)
> 	• I can compare P and P2 on node 1 and they are identical
> 	• I'm restarting node 1
> 	• On node 1 I generate the same pid P as in step 1 (<0.X.0>)
> 	• I repeat step 3, again receive initial pid as P2
> 	• P2 is recognized as local pid (<0.X.0>) - as before
> 	• But now P == P2 returns false.
> 	• Also P == list_to_pid(pid_to_list(P2)) returns true
> Could someone explain this behavior?
> What is changing in internal pid representation after node restart so comparison in step 10 returns false? And why comparison in step 11 returns true?
> 
> My code (first lines for node 1, after empty line code for node 2):
> ------------
> erl -sname n1 -setcookie t
>  
> erl -sname n2 -setcookie t
> ------------
> net_kernel:connect_node('n2@REDACTED').
> global:register_name(n1, self()).
>  
> global:register_name(n2, self()).
> ------------
> P = pid(0,1,0).
> global:send(n2, P).
>  
> receive P -> P end.
> ------------
> receive P2 -> P2 end.
> P == P2. % this will return true
>  
> global:send(n1, P).
> ------------
> %restart n1
> net_kernel:connect_node('n2@REDACTED').
> global:register_name(n1, self()).
> P = pid(0,1,0).
> receive P2 -> P2 end.
> P == P2. % this will return false
>  
> global:send(n1, P).
> ------------
> 
> Thanks,
> Pavel
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions

"Installing applications can lead to corruption over time. Applications gradually write over each other's libraries, partial upgrades occur, user and system errors happen, and minute changes may be unnoticeable and difficult to fix"






More information about the erlang-questions mailing list