Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the point of Spawn(Node, Fun) on erlang, if Node has to have the same module loadable as a client node?

Why create illusion that you are sending a Fun to remote node to execute in a new process? If client node has to have same module loadable with the Fun defined as a server node anyway. Why not only spawn(Node, M, F, A) then, which makes it clear that you are sending a definition of a function call, not Fun itself.

like image 506
Sharas Avatar asked Aug 31 '16 17:08

Sharas


People also ask

What is the difference between Spawn() and fork() methods in NodeJS?

In this article, we will discuss the difference between spawn () and fork () methods in Node.js. Both are ways to create child processes in Node.js in order to handle increasing workloads. Spawn () method: The spawn process initiates a command in a new process. We can pass the command as an argument to it.

What is an example of a spawn event?

Example: This is a very simple and general example of the use of spawn. We first required spawn by destructuring, then create a child process by passing arguments. Then register a stdout event on that child process. Message sent from child.js is printing in file server.js due to the use of fork child process.

What is the use of spawn in shell script?

The different shell can be specified as a string. The default value is false which implies no shell. Return Value: It returns an instance of the child process. Example: This is a very simple and general example of the use of spawn. We first required spawn by destructuring, then create a child process by passing arguments.

What is the default value of Spawn command in Linux?

The default value is an empty array. shell: Accepts a boolean value. If true, runs the command inside of a shell. The different shell can be specified as a string. The default value is false which implies no shell. Return Value: It returns an instance of the child process. Example: This is a very simple and general example of the use of spawn.


2 Answers

Let's consider two possible cases

Functions referring to module functions

Fun = fun file:getcwd/0,
erlang:spawn(Node, Fun). 

In this case Fun indeed should be loadable at the remote side.

Anonymous functions

Fun = fun() -> io:format("My node is ~p~n", [node()]) end,
erlang:spawn(Node, Fun). 

They are callable also.

Summarizing

While there some limitations implied to a function, that can be spwaned remotely, this form is still suitable and can be dropped, because then second case would become impossible

Also

Some misconceptions might go from this article

Actually, if you run erlang:fun_info for anonymous function, you'll see, that it provides implementation in a form of AST

(b@lol4t0-home)21> rp(erlang:fun_info(fun() -> io:format("My node is ~p~n", [node()]) end)). 
[{pid,<0.96.0>},
 {module,erl_eval},
 {new_index,20},
 {new_uniq,<<99,62,121,82,122,95,246,237,63,72,118,40,4,
             25,16,50>>},
 {index,20},
 {uniq,52032458},
 {name,'-expr/5-fun-3-'},
 {arity,0},
 {env,[{[],
        {eval,#Fun<shell.21.31625193>},
        {value,#Fun<shell.5.31625193>},
        [{clause,1,[],[],
                 [{call,1,
                        {remote,1,{atom,1,io},{atom,1,format}},
                        [{string,1,"My node is ~p~n"},
                         {cons,1,{call,1,{atom,1,node},[]},{nil,1}}]}]}]}]},
 {type,local}]
like image 189
Lol4t0 Avatar answered Nov 15 '22 10:11

Lol4t0


The example below shows that the remote node can execute a code that was never loaded on it, even a call to an anonymous function that was defined on the caller node:

on node titi

Erlang/OTP 19 [erts-8.0] [64-bit] [smp:4:4] [async-threads:10]

Eshell V8.0  (abort with ^G)
(titi@XXXXXXXX)1> net_adm:ping(toto@XXXXXXXX).
pong
(titi@XXXXXXXX)2> F = fun F(X) -> receive {plus,N} -> F(X+N); get -> io:format("state is ~p~n",[X]), F(X); stop -> bye end end. 
#Fun<erl_eval.30.52032458>
(titi@XXXXXXXX)3> G = fun() -> register(server,self()), F(0) end.
#Fun<erl_eval.20.52032458>
(titi@XXXXXXXX)4> spawn(toto@XXXXXXXX,G).
<7039.67.0>
state is 0           
state is 5           
state is 10          
(titi@XXXXXXXX)5> 

on node toto

Erlang/OTP 19 [erts-8.0] [64-bit] [smp:4:4] [async-threads:10]

Eshell V8.0  (abort with ^G)
(toto@XXXXXXXX)1> server ! get. % will print state is 0
get
(toto@XXXXXXXX)2> server ! {plus,5}. % new state = 5
{plus,5}
(toto@XXXXXXXX)3> server ! get. % will print state is 5    
get
(toto@XXXXXXXX)4> server ! {plus,5}. % new state = 10
{plus,5}
(toto@XXXXXXXX)5> server ! get. % will print state is 10     
get
(toto@XXXXXXXX)6> server ! stop. % ends the server process    
stop
(toto@XXXXXXXX)7> server ! get. % message will fail
** exception error: bad argument
     in operator  !/2
        called as server ! get
(toto@XXXXXXXX)8> 

I also checked that if you replace the code {plus,N} -> F(X+N); by {plus,N} -> F(maps:put(X,X+N,maps:new())); which is calling a module not loaded by the shell at start, it works fine as well.

Edit

Read the comments, it seems that doing the test in the shell is not the right way, 2 conclusions though:

  • do not rely on the shell only to make verifications,
  • there should be a way to execute on the remote node a code that was only known on the caller node since the shell can do it...
like image 24
Pascal Avatar answered Nov 15 '22 09:11

Pascal